Reputation:
Consider the following snippet:
struct Foo
{
static const T value = 123; //Where T is some POD-type
};
const T Foo::value; //Is this required?
In this case, does the standard require us to explicitly declare value in a translation unit? It seems I have conflicting information; boost and things like numeric_limits from the STL seem to do this sort of thing just like in my snippet.
OTOH, I remember reading somewhere (albeit a long long time ago) that you're still required to provide a declaration in a translation unit.
If this is the case, what about template specialization? Will each specialization require a declaration?
I'd appreciate your comments as to what the "right way" is.
Upvotes: 0
Views: 445
Reputation: 507005
You have to provide a definition in a translation unit too, in case you use the value variable. That means, if for example you read its value.
The important thing is that the compiler is not required to give a warning or error if you violate that rule. The Standard says "no diagnostic required" for a violation.
In the next C++ Standard version, the rule changed. A variable is not used when it is used as a constant expression. Simply reading value above where the variable is initialized directly in the class means that still no definition is required then.
See the definition of use
in section 3.2 One Definition Rule
of the Standard and requirement for a definition for static data-members in 9.4.2, paragraph 4 and 5
(in the C++98 Standard. Appears in paragraph 3 and 4 in the n2800 draft of the next Standard).
Correction: The rule already changed for c++03: If the variable appears where a integral constant expression is required, no definition is needed (quoting from an unofficial revisions list for the 2003 update), see resolution for this language defect report:
An expression is potentially evaluated unless it appears where an integral constant expression is required (see 5.19), is the operand of the sizeof operator (5.3.3), or is the operand of the typeid operator and the expression does not designate an lvalue of polymorphic class type (5.2.8)...
Note that even then, many uses are in cases where an integral constant is not required. Cases where one is, is in array dimensions or in template metaprogramming. So strictly speaking (see this report), only the c++1x solution provides really guarantee that in obvious cases also like "s == string::npos"
where an integral constant is not required the definition of the static member is not needed, because the next Standard has a different, better wording of 3.2. This is however quite theoretical stuff, since most (all?) compiler don't moan anyway. Thanks for the guy in the comment section for telling me.
Upvotes: 3
Reputation: 32389
You don't have to provide a definition for static integral constant members if you don't use them in some way that requires them to be stored in memory somewhere (e.g. take the address of such a member). See Stroustrup's The C++ Programming Language, section 10.4.6.2.
Edit: Oops, I just re-read the question, and the question was for some type T. In general you would need to provide a definition, I agree. But if you used something from the int family, you wouldn't necessarily have to (with the caveat above).
Upvotes: 0
Reputation: 111130
To add on to what litb said, from my copy of n2798:
9.4.2
[...]
2 The declaration of a static data member in its class definition is not a definition and
may be of an incomplete type other than cv-qualified void. The definition for a static
data member shall appear in a namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator.
Upvotes: 1