Re: template const trick versus myers singleton - global data revisited
* Technical:
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 file,
which is the main point of the templated const trick, then you risk multiple
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'?
Not as far as I know, except replacing 'trick' with 'idiom' or 'technique'.
And as far as I know using a class template solely in order to define (and
possibly inherit) constants in header files is my invention, first and only time
used for helping define 'char' and 'wchar_t' versions of the same string
constants, and if so, then I get to name it. ;-)
But then, every thing I've ever thought I'd invented has turned out to to have
been invented by at least 1 person prior to myself, and I don't discount the
possibility that I've simply seen it somewhere, e.g. in a newsgroup posting.
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
Because here PI has internal linkage, which means that (when disregarding
optimization) there's one copy of it in every compilation unit where it's used,
each compilation unit using its own copy -- instead of multiple definitions of
a common single program-wide instance.
Internal linkage is the default for a const at namespace scope.
And so above the keyword 'static' is redundant -- unlike my typo below...
Not sure what you mean about "static keyword" but the templated const allows 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 optimizations.
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.
I'm still not sure exactly what you mean.
Not for this concrete example, because the static initialization fiasco is about
dynamic initialization, initialization that involves execution of user code, and
your constants are of built-in type:
First, static initialization is performed, which consists of, in order,
zero-initialization, and then
initialization with constant expressions (compile time constants),
then
dynamic initialization.
And the problem is that C++ does not strictly define the order that different
compilation units' dynamic initialization is performed in.
So with e.g. std::string constants the templated const trick in general runs the
risk of a static initialization order fiasco, since it just defines an ordinary
namespace scope constant, which might be accessed (from some other compilation
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?
Yes regarding the second 'static' you added here, and sorry; I meant to write
inline std::string const& piChars()
{
static std::string const theValue = "3.141592654";
return theValue;
}
The first 'static' you added, however, would make this function have internal
linkage, and so would (modulo optimization) place a copy of both the function
and its wrapped constant in every compilation unit where it's used.
The 'inline' is to allow multiple definitions of the function (one per
compilation unit, only one of them being picked for the final program).
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
Depends what you mean. The templated const trick is mostly for where you need a
/non-integral/ type constant. That is, except for possible static initialization
fiasco issues you can safely do this, in a header file:
template< typename Dummy >
struct Names_ { static std::string const cppLanguageCreator; };
template< typename Dummy >
std::string const Names_<Dummy>::cppLanguageCreator = "Bjarne Stroustrup";
typedef Names_<void> Names;
Cheers & hth.,
- Alf
--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! :-) Just going there is good. Linking
to it is even better! Thanks in advance!