Static Constant Class Members - c++

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.

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.

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.

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).

Related

It seems the current standard draft cannot interpret why two structured binding declaration conflict with each other

struct A{
int a;
};
struct B{
int b;
};
auto&& [x] = A{}; //#1
auto&& [x] = B{}; //#2
int main(){
}
In this example, all compilers give an error that the x at #2 conflicts with that introduced at #1. However, IIUC, there's no rule in the post-C++20 working draft standard which can interpret what's the reason.
First, in my opinion, the declaration at #2 and the declaration at #1 declare the same entity. They correspond due to:
basic.scope#scope-3
Two declarations correspond if they (re)introduce the same name, both declare constructors, or both declare destructors, unless
[...]
They declare the same entity per basic.link#8
Two declarations of entities declare the same entity if, considering declarations of unnamed types to introduce their names for linkage purposes, if any ([dcl.typedef], [dcl.enum]), they correspond ([basic.scope.scope]), have the same target scope that is not a function or template parameter scope, and either
they appear in the same translation unit, or
[...]
So, as far as now, they declare the same entity and they shouldn't be considered as potentially conflict per basic.scope#scope-4
Two declarations potentially conflict if they correspond and cause their shared name to denote different entities([basic.link]). The program is ill-formed if, in any scope, a name is bound to two declarations that potentially conflict and one precedes the other ([basic.lookup]).
Since they denote the same entity, as aforementioned, they do not potentially conflict.
They still do not violate this rule:
basic.link#11
For any two declarations of an entity E:
If one declares E to be a variable or function, the other shall declare E as one of the same type.
[...]
Since structured bindings are not mentioned in this list, they do not violate this rule. Similar, they do not violate One-definition rule
No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, template, default argument for a parameter (for a function in a given scope), or default template argument.
At least, according to what the relevant rules say, the two declarations in this example shouldn't result in any program ill-formed. If I don't miss some other rules, Can it be considered as vague in the standard which cannot interpret why two structured binding declarations conflict with each other in this case? This case is more underspecified in the N4861
This is just a missing case in [basic.link]/11: that if one (of the two declarations) declares a structured binding, the program is ill-formed. (One could alternatively merely require that the other also declare a structured binding and then extend the list in [basic.def.odr]/1, but that’s more complicated and suggests that it might be possible to redefine it in another translation unit.)
You are citing text from a working draft of a post-C++20 version of the language. As such, the behavior it describes is not likely implemented by any compiler currently existing. As it is a working draft, it likely contains a number of language defects and/or bugs, so trying to learn from it is not a productive activity.
All of the "correspond" language you cite is adopted from P1787, which is not part of any C++ standard actual compilers implement. As such, compilers are providing you with the C++20 functionality, and under those rules, these clearly conflict.
There may be some defective wording in P1787, but that's expected with complex proposals and working drafts of a standard. File a defect report on it.

Can using a lambda in header files violate the ODR?

Can the following be written in a header file:
inline void f () { std::function<void ()> func = [] {}; }
or
class C { std::function<void ()> func = [] {}; C () {} };
I guess in each source file, the lambda's type may be different and therefore the contained type in std::function (target_type's results will differ).
Is this an ODR (One Definition Rule) violation, despite looking like a common pattern and a reasonable thing to do? Does the second sample violate the ODR every time or only if at least one constructor is in a header file?
This boils down to whether or not a lambda's type differs across translation units. If it does, it may affect template argument deduction and potentially cause different functions to be called - in what are meant to be consistent definitions. That would violate the ODR (see below).
However, that isn't intended. In fact, this problem has already been touched on a while ago by core issue 765, which specifically names inline functions with external linkage - such as f:
7.1.2 [dcl.fct.spec] paragraph 4 specifies that local static variables and string literals appearing in the body of an inline function with
external linkage must be the same entities in every translation unit
in the program. Nothing is said, however, about whether local types
are likewise required to be the same.
Although a conforming program could always have determined this by use
of typeid, recent changes to C++ (allowing local types as template
type arguments, lambda expression closure classes) make this question
more pressing.
Notes from the July, 2009 meeting:
The types are intended to be the same.
Now, the resolution incorporated the following wording into [dcl.fct.spec]/4:
A type defined within the body of an extern inline function is the same type in every translation unit.
(NB: MSVC isn't regarding the above wording yet, although it might in the next release).
Lambdas inside such functions' bodies are therefore safe, since the closure type's definition is indeed at block scope ([expr.prim.lambda]/3).
Hence multiple definitions of f were ever well-defined.
This resolution certainly doesn't cover all scenarios, as there are many more kinds of entities with external linkage that can make use of lambdas, function templates in particular - this should be covered by another core issue.
In the meantime, Itanium already contains appropriate rules to ensure that such lambdas' types coincide in more situations, hence Clang and GCC should already mostly behave as intended.
Standardese on why differing closure types are an ODR violation follows. Consider bullet points (6.2) and (6.4) in [basic.def.odr]/6:
There can be more than one definition of […]. Given such an entity named D defined in more than one translation unit, then each definition of D shall consist of the
same sequence of tokens; and
(6.2) - in each definition of D, corresponding names, looked up
according to [basic.lookup], shall refer to an entity defined within
the definition of D, or shall refer to the same entity, after
overload resolution ([over.match]) and after matching of partial
template specialization ([temp.over]), […]; and
(6.4) - in each definition of D, the overloaded operators referred to,
the implicit calls to conversion functions, constructors,
operator new functions and operator delete functions, shall refer to
the same function, or to a function defined within the definition of
D; […]
What this effectively means is that any functions called in the entity's definition shall be the same in all translation units - or have been defined inside its definition, like local classes and their members. I.e. usage of a lambda per se is not problematic, but passing it to function templates clearly is, since these are defined outside the definition.
In your example with C, the closure type is defined within the class (whose scope is the smallest enclosing one). If the closure type differs in two TUs, which the standard may unintentionally imply with the uniqueness of a closure type, the constructor instantiates and calls different specializations of function's constructor template, violating (6.4) in the above quote.
UPDATED
After all I agree with #Columbo answer, but want to add the practical five cents :)
Although the ODR violation sounds dangerous, it's not really a serious problem in this particular case. The lambda classes created in different TUs are equivalent except their typeids. So unless you have to cope with the typeid of a header-defined lambda (or a type depending on the lambda), you are safe.
Now, when the ODR violation is reported as a bug, there is a big chance that it will be fixed in compilers that have the problem e.g. MSVC and probably some other ones which don't follow the Itanium ABI. Note that Itanium ABI conformant compilers (e.g. gcc and clang) are already producing ODR-correct code for header-defined lambdas.

Example of non odr-used variable defined in the program [duplicate]

This just came up in the context of another question.
Apparently member functions in class templates are only instantiated if they are ODR-used.
Could somebody explain what exactly that means. The wikipedia article on One Definition Rule (ODR) doesn't mention "ODR-use".
However the standard defines it as
A variable whose name appears as a potentially-evaluated expression
is odr-used unless it is an object that satisfies the requirements for
appearing in a constant expression (5.19) and the lvalue-to-rvalue
conversion (4.1) is immediately applied.
in [basic.def.odr].
Edit: Apparently this is the wrong part and the entire paragraph contains multiple definitions for different things. This might be the relevant one for class template member function:
A non-overloaded function whose name appears as a
potentially-evaluated expression or a member of a set of candidate
functions, if selected by overload resolution when referred to from a
potentially-evaluated expression, is odr-used, unless it is a pure
virtual function and its name is not explicitly qualified.
I do however not understand, how this rule works across multiple compilation units? Are all member functions instantiated if I explicitly instantiate a class template?
It's just an arbitrary definition, used by the standard to
specify when you must provide a definition for an entity (as
opposed to just a declaration). The standard doesn't say just
"used", because this can be interpreted diversely depending on
context. And some ODR-use doesn't really correspond to what one
would normally associate with "use"; for example, a virtual
function is always ODR-used unless it is pure, even if it isn't
actually called anywhere in the program.
The full definition is in §3.2, second paragraph, although this
contains references to other sections to complete the
definition.
With regards to templates, ODR-used is only part of question;
the other part is instantiation. In particular, §14.7 covers
when a template is instantiated. But the two are related: while
the text in §14.7.1 (implicit instantiation) is fairly long, the
basic principle is that a template will only be instantiated if
it is used, and in this context, used means ODR-used. Thus,
a member function of a class template will only be instantiated
if it is called, or if it is virtual and the class itself is
instantiated. The standard itself counts on this in many
places: the std::list<>::sort uses < on the individual
elements, but you can instantiate a list over an element type
which doesn't support <, as long as you don't call sort on
it.
In plain word, odr-used means something(variable or function) is used in a context where the definition of it must be present.
e.g.,
struct F {
static const int g_x = 2;
};
int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed.
// so it's OK without the definition of g_x
vector<int> vi;
vi.push_back( F::g_x ); // Error, this is odr-used, push_back(const int & t) expect
// a const lvalue, so it's definition must be present
Note, the above push_back passed in MSVC 2013. This behavior is not standard compliant - both gcc 4.8.2 and clang 3.8.0 failed, with error message:
undefined reference to F::g_x

What does it mean to "ODR-use" something?

This just came up in the context of another question.
Apparently member functions in class templates are only instantiated if they are ODR-used.
Could somebody explain what exactly that means. The wikipedia article on One Definition Rule (ODR) doesn't mention "ODR-use".
However the standard defines it as
A variable whose name appears as a potentially-evaluated expression
is odr-used unless it is an object that satisfies the requirements for
appearing in a constant expression (5.19) and the lvalue-to-rvalue
conversion (4.1) is immediately applied.
in [basic.def.odr].
Edit: Apparently this is the wrong part and the entire paragraph contains multiple definitions for different things. This might be the relevant one for class template member function:
A non-overloaded function whose name appears as a
potentially-evaluated expression or a member of a set of candidate
functions, if selected by overload resolution when referred to from a
potentially-evaluated expression, is odr-used, unless it is a pure
virtual function and its name is not explicitly qualified.
I do however not understand, how this rule works across multiple compilation units? Are all member functions instantiated if I explicitly instantiate a class template?
It's just an arbitrary definition, used by the standard to
specify when you must provide a definition for an entity (as
opposed to just a declaration). The standard doesn't say just
"used", because this can be interpreted diversely depending on
context. And some ODR-use doesn't really correspond to what one
would normally associate with "use"; for example, a virtual
function is always ODR-used unless it is pure, even if it isn't
actually called anywhere in the program.
The full definition is in §3.2, second paragraph, although this
contains references to other sections to complete the
definition.
With regards to templates, ODR-used is only part of question;
the other part is instantiation. In particular, §14.7 covers
when a template is instantiated. But the two are related: while
the text in §14.7.1 (implicit instantiation) is fairly long, the
basic principle is that a template will only be instantiated if
it is used, and in this context, used means ODR-used. Thus,
a member function of a class template will only be instantiated
if it is called, or if it is virtual and the class itself is
instantiated. The standard itself counts on this in many
places: the std::list<>::sort uses < on the individual
elements, but you can instantiate a list over an element type
which doesn't support <, as long as you don't call sort on
it.
In plain word, odr-used means something(variable or function) is used in a context where the definition of it must be present.
e.g.,
struct F {
static const int g_x = 2;
};
int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed.
// so it's OK without the definition of g_x
vector<int> vi;
vi.push_back( F::g_x ); // Error, this is odr-used, push_back(const int & t) expect
// a const lvalue, so it's definition must be present
Note, the above push_back passed in MSVC 2013. This behavior is not standard compliant - both gcc 4.8.2 and clang 3.8.0 failed, with error message:
undefined reference to F::g_x

What am I allowed to do with a static, constexpr, in-class initialized data member?

This is probably a bit of an unusual question, in that it asks for a fuller explanation of a short answer given to another question and of some aspects of the C++11 Standard related to it.
For ease of reference, I shall sum up the referenced question here. The OP defines a class:
struct Account
{
static constexpr int period = 30;
void foo(const int &) { }
void bar() { foo(period); } //no error?
};
and is wondering why he gets no error about his usage of an in-class initialized static data member (a book mentioned this to be illegal). Johannes Schaub's answer states, that:
This violates the One Definition Rule;
No diagnostics is required.
As much as I rely the source and validity of this answer, I honestly dislike it because I personally find it too cryptic, so I tried to work out a more meaningful answer myself, with only partial success. Relevant seems to be § 9.4.2/4:
"There shall be exactly one definition of a static data member that is odr-used (3.2) in a program; no diagnostic is required" [Emphases are mine]
Which gets me a bit closer to the point. And this is how § 3.2/2 defines an odr-used variable:
"A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied" [Emphases are mine]
In the OP's question, variable period clearly satisfies the requirements for appearing in a constant expression, being a constexpr variable. So the reason must be certainly found in the second condition: "and the lvalue-to-rvalue conversion (4.1) is immediately applied".
This is where I have troubles interpreting the Standard. What does this second condition actually mean? What are the situations it covers? Does it mean that a static constexpr variable is not odr-used (and therefore can be in-class initialized) if it is returned from a function?
More generally: What are you allowed to do with a static constexpr variable so that you can in-class initialize it?
Does it mean that a static constexpr variable is not odr-used (and
therefore can be in-class initialized) if it is returned from a
function?
Yes.
Essentially, as long as you treat it as a value, rather than an object, then it is not odr-used. Consider that if you pasted in the value, the code would function identically- this is when it is treated as an rvalue. But there are some scenarios where it would not.
There are only a few scenarios where lvalue-to-rvalue conversion is not performed on primitives, and that's reference binding, &obj, and probably a couple others, but it's very few. Remember that, if the compiler gives you a const int& referring to period, then you must be able to take it's address, and furthermore, this address must be the same for each TU. That means, in C++'s horrendous TU system, that there must be one explicit definition.
If it is not odr-used, the compiler can make a copy in each TU, or substitute the value, or whatever it wants, and you can't observe the difference.
You missed a part of the premise. The class definition give above is completely valid, if you also define Account::period somewhere (but without providing an initializer). See the last sentance of 9.4.2/3:
The member shall still be defined in a namespace scope if it is odr-used
(3.2) in the program and the namespace scope definition shall not
contain an initializer.
This entire discussion only applies to static constexpr data members, not to namespace-scope static variables. When static data members are constexpr (rather than simply const) you have to initialize them in the class definition. So your question should really be: What are you allowed to do with a static constexpr data member so that you don't have to provide a definition for it at namespace scope?
From the preceding, the answer is that the member must not be odr-used. And you already found relevant parts of the definition of odr-used. So you can use the member in a context where it is not potentially-evaluated - as an unevaluated operand (for example of sizeofor decltype) or a subexpression thereof. And you can use it in an expression where the lvalue-to-rvalue conversion is immediately applied.
So now we are down to What uses of a variable cause an immediate lvalue to rvalue conversion?
Part of that answer is in §5/8:
Whenever a glvalue expression appears as an operand of an operator
that expects a prvalue for that operand, the lvalue-to-rvalue (4.1),
array-to-pointer (4.2), or function-to-pointer (4.3) standard
conversions are applied to convert the expression to a prvalue.
For arithmetic types that essentially applies to all operators that apply standard arithmetic conversions. So you can use the member in various arithmetic and logical operations without needing a definition.
I can't enumerate all things, you can or can't do here, because the requirements that something be a [g]lvalue or [p]rvalue are spread across the standard. The rule of thumb is: if only the value of the variable is used, a lvalue to rvalue conversion is applied; if the variable is used as an object, it is used as lvalue.
You can't use it in contexts where an lvalue is explicitly required, for example as argument to the address-of operator or mutating operators). Direct binding of lvalue references (without conversion) is such a context.
Some more examples (without detailed standardese analysis):
You can pass it to functions, unless the function parameter is a reference to which the variable can be directly bound.
For returning it from a function: if implicit conversion to the return type involves a user-defined conversion function, the rules for passing to a function apply. Otherwise you can return it, unless the function returns an lvalue (a reference) referring directly to the variable.
The key rule for odr-used variables, the "One Definition Rule" is in 3.2/3:
Every program shall contain exactly one definition of every non-inline
function or variable that is odr-used in that program; no diagnostic
required.
The "no diagnostic required" part means that programs violating this rule cause undefined behavior, which may range from failing to compile, compiling and failing in surprising ways to compiling and acting as if everything was OK. And your compiler need not warn you about the problem.
The reason, as others have already indicated, is that many of these violations would only be detected by a linker. But optimizations may have removed references to objects, so that no cause for linkage failure remains or else linking may sometimes occur only at runtime or be defined to pick an arbitrary instance from multiple definitions of a name.