When the constexpr
was introduced to C++ I started to write my compile time constants as constexpr static
member variables instead of using the enum
hack.
So I know about the subtle difference that you cannot take the address of a constant defined with enum
, where in the constexpr
case you can. Since you don't want to do that, so it's fine. But now I stumbled upon some code where I'm not sure whether you might accidentally take the address.
#include <iostream>
struct A
{
constexpr static unsigned c1 = 1;
enum{ c2 = 2 };
};
template<typename T>
auto foo(T&& p)
{
return p;
}
int main()
{
std::cout << foo(A::c1) << " " << foo(A::c2) << std::endl;
return 0;
}
gcc 7
and clang 4
will compile this code just fine, where any older versions of these compilers will complain about an undefined reference of A::c1
.
If I understand this correctly, the function foo
takes the A::c1
expression as some kind of reference and thus needs to take its address, which leads to the undefined reference.
What is the correct behavior? Does the standard require me to define the member variable just to be able to use them in the context of perfect forwarding?
Edit:
I just noticed, gcc 7
as well as clang 4
will also complain about the undefined reference if you use -std=c++14
instead of -std=c++1z
. So was there a related change in the standard?