Re: template const trick versus myers singleton - global data
revisited
On Jun 20, 8:18 pm, "Alf P. Steinbach" <al...@start.no> wrote:
In a single file program this will work, but if you do it in a header fil=
e,
which is the main point of the templated const trick, then you risk multi=
ple
definitions, that is, running afoul of the One Definition Rule.
Instead do
template< typename Dummy >
double const consts<Dummy>::PI = 3.14159;
There is a special exemption for this, or put another way, the ODR allows=
this,
in order to make it possible to define templates in header files.
Is there another name for the 'templated const trick'? With regards
to the ODR (this is where I get confused at times), why wouldn't i run
the risk of violation if I do:
// header.h
#ifndef HEADER
#define HEADER
static const double PI = 3.14159;
#endif
// foo.cpp - assume there's a foo.h
# include "header.h"
foo::foo()
{ std::cout << PI << '\n' }
// bar.cpp - assume there's a bar.h
# include "header.h"
bar::bar()
{ std::cout << PI << '\n' }
Not sure what you mean about "static keyword" but the templated const all=
ows you
to define constants in a header file and for each such constant have only=
one
occurrence of the value in the final program, without relying on optimiza=
tions.
Well I was referring to 'form b'. The c_constants class. The one
advantage I see with the singleton approach is static keyword is not
required on for the variable PI and PI can be initialized using the
constructor. That's perhaps the only drawback I see with the
templated const trick. I can't use a constructor to initialize PI
while achieving the objective.
Not for this concrete example, because the static initialization fiasco i=
s about
dynamic initialization, initialization that involves execution of user co=
de, and
your constants are of built-in type:
First, static initialization is performed, which consists of, in o=
rder,
zero-initialization, and then
initialization with constant expressions (compile time consta=
nts),
then
dynamic initialization.
And the problem is that C++ does not strictly define the order that diffe=
rent
compilation units' dynamic initialization is performed in.
So with e.g. std::string constants the templated const trick in general r=
uns the
risk of a static initialization order fiasco, since it just defines an or=
dinary
namespace scope constant, which might be accessed (from some other compil=
ation
unit's dynamic initialization) before its constructor runs.
One way to avoid that is to wrap the constant in a function:
inline std::string const& piChars()
{
std::string const theValue = "3.141592654";
return theValue;
}
That should really be:
inline static std::string const& piChars()
{ static std::string const theValue = "3.141592654"; return
theValue; }
Correct?
instead of
std::string const piChars = "3.141592654";
Of course only static ocnst integral types can be defined within the
composite type 'consts' but given the context point taken