I have the following C++11 code (simplified version):
struct Info
{
const char * name;
int version;
};
class Base
{
public:
const Info info;
Base (Info info) : info (info) {}
};
class Derived : public Base
{
public:
static constexpr Info info = {"Foobar", 2};
Derived () : Base (info) {}
};
int main ()
{
static Derived derived;
return 0;
}
GCC 4.9.1 compiles and links this code fine. Clang 3.5.0, on the other hand, complains about an undefined reference:
/tmp/test-109c5c.o: In function `main':
test.cc:(.text+0x1c): undefined reference to `Derived::info'
test.cc:(.text+0x22): undefined reference to `Derived::info'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Which is right? Is this code legal or not? My understanding of the rules regarding static constexpr members (based mostly on this question) is that an out-of-class definition is needed only when the address of the variable is taken. But I'm not taking the address of Derived::info or using a reference to it anywhere; I'm only passing it by value to the Base constructor.
Various workarounds that I've found:
- Make both constructors (Base and Derived) constexpr. This may or may not be an option with the real classes, which are more complex than the ones in the example. I'm going to try it, anyway.
- Declare the instance of Derived in main with automatic rather than static duration. This is not an option for the real project: the Derived class is a plugin implementation, and an instance of it needs to be exported as a public symbol in a shared object.
- Remove Derived::info entirely and call the Base constructor with a brace-initialized temporary object instead, i.e.
Base ({"Foobar", 2})
. This solution would work, but it gets ugly (in my opinion) as more members are added to struct Info.