The following code compiles ok with Intel-2015 but fails with gcc 4.8.3 Who is right?
#include <iostream>
void f( int const& x ) { std::cout << x << std::endl; }
struct S
{
static constexpr int ce = 42;
};
int main()
{
f(S::ce);
return 0;
}
g++ error:
/tmp/ccOIxa2V.o: In function `main':
test_constexpr.cpp:(.text+0x36): undefined reference to `S::ce'
collect2: error: ld returned 1 exit status
Because the function f takes a reference argument, there has to be a definition of S::ce that a reference can point to at runtime; the compiler can't just replace the argument with a literal 42. So you have to add an out-of-class definition:
const int S::ce;
just like you would with a non-constexpr variable. This allocates a memory location for the value at runtime, for use by references and other things that couldn't be computed at compile time.
See this GCC bug report (which has comments explaining why it isn't actually a bug) for more information.
I think GCC is right. BTW, CLang 3.5.1 gives the same error.
The thing is that constant static variables are allowed not to be defined only if their address is not taken and they are not bound to references.
Your example bounds a reference to it, so the explicit definition is needed.
From the C++11 draft (9.4.2.3), conveniently edited:
A static data member of literal type can be declared in the class definition with the constexpr specifier; [...] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program [...].
And in 3.2:
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.
That lvalue-to-rvalue conversion stuff is, roughly speaking, done everytime the variable is used except when binding a reference or as argument to the unary take-address operator &.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With