Is it legal C++ to pass the address of a static co

2019-02-19 07:01发布

问题:

I'm having trouble deciding whether not this code should compile or if just both compilers I tried have a bug (GCC 4.2 and Sun Studio 12). In general, if you have a static class member you declare in a header file you are required to define it in some source file. However, an exception is made in the standard for static const integrals. For example, this is allowed:

#include <iostream>

struct A {
    static const int x = 42;
};

With no need to add a definition of x outside the class body somewhere. I'm trying to do the same thing, but I also take the address of x and pass it to a template. This results in a linker error complaining about a lack of definition. The below example doesn't link (missing a definition for A::x) even when it's all in the same source file:

#include <iostream>

template<const int* y>
struct B {
    static void foo() { std::cout << "y: " << y << std::endl; }
};

struct A {
    static const int x = 42;
    typedef B<&x> fooness;
};

int main()
{
    std::cout << A::x << std::endl;
    A::fooness::foo();
}

Which is bizarre since it works as long as I don't pass the address to a template. Is this a bug or somehow technically standards compliant?

Edit: I should point out that &A::x is not a runtime value. Memory is set aside for statically allocated variables at compile time.

回答1:

To be a well formed program you stil have to have the defintion of the static variable (without an initializer in this case) if it actually gets used, and taking the address counts as a use:

  • C++2003 Standard: 9.4.2 Static data members Paragraph 4 (bold added)

If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer



回答2:

You are trying to pass a runtime value to a template, that's not possible. The only allowed template parameters are types (class/typename) or integral constant values (int/bool/etc).



回答3:

Interesting, it compiled fine for me on VS 2008. I kind of assumed that the error came from the typedef because at compile time when it tries to compile 'B' with &x as the template type it doesn't then know where the address of x will be. Still... it compiles and gives a reasonable output.



回答4:

I could see how one might expect this to compile anyway.

The address of a static const isn't really a runtime value and can be fully resolved at link time.