0

The following code fails to link with g++ 4.8.2:

#include <map>

struct Foo
{
    constexpr static int foo = 1;
};

static std::map<int, int> map {{1, Foo::foo}};

int main()
{
    return Foo::foo;
}

I get the following error:

g++ -std=c++11 -o foo foo.cc
/tmp/ccZXCwiK.o: In function `__static_initialization_and_destruction_0(int, int)':
foo.cc:(.text+0x51): undefined reference to `Foo::foo'

If I comment out the map, things link just fine. Is this a compiler bug, or is it some corner case I am missing in the standard?

3
  • @LightnessRacesinOrbit coliru.stacked-crooked.com/a/d9da4dacc301287d Commented Dec 12, 2013 at 18:09
  • And again, a + magically fixes things: static std::map<int, int> map {{1, +Foo::foo}}; works fine. Commented Dec 12, 2013 at 18:43
  • 1
    @DyP : Wow. That's quite amazing and quite frightening. I would never put that in my code because the comment I would have to add explaining why it was there would be worse than the "fix." Commented Dec 12, 2013 at 21:36

1 Answer 1

7

You forgot to define the static member.

As soon as you odr-use it, a full definition is required. Yes, even though it has an inline initialiser and, yes, even though it's marked constexpr.

Add:

constexpr int Foo::foo;

Your original code works for me in GCC 4.8.1 via both ideone.com and Coliru, but that's with optimisations turned on (so that constant is likely being supplanted for the symbol in each case). With optimisations off, the error is reproducible.

Sign up to request clarification or add additional context in comments.

1 Comment

Interesting. This came up in an instance where I was replacing a macro with a constexpr. Figuring out where odr-use applies is definitely causing me to slip up.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.