开发者

Is this code broken or is there a bug in g++?

开发者 https://www.devze.com 2023-03-19 05:59 出处:网络
For some strange reason g++ (versions 4.5.0 and 4.5.2) cannot compile this code: bool somefunc() { return false;

For some strange reason g++ (versions 4.5.0 and 4.5.2) cannot compile this code:

bool somefunc() {
    return false;
}

class C {
  public:
    static const int a = 0;
    static const int b = 1;
};

class myclass {
  public:
    int check() {
        return somefunc() ? C::a : C::b;
        // if(somefunc()) return C::a; else return C::b;
    }
};

int main() {
    myclass obj;
    obj.check();
    return 0;
}

It gives me this error:

/tmp/ccyvvTUy.o:/h开发者_JAVA技巧ome/mati/test.cpp:14: undefined reference to `C::a'
/tmp/ccyvvTUy.o:/home/mati/test.cpp:14: undefined reference to `C::b'
collect2: ld returned 1 exit status

What's strange if I change problematic line to the commented line it compiles fine. Is it something wrong with my code and something I don't understand about C++ or is it just a bug in G++ ?


There is an ongoing debate on whether this code is actually legal or not.

Either way, according to some readings the constants actually do need to be defined before usage, not just declared. That is,

class C {
  public:
    static const int a = 0;
    static const int b = 1;
};

const int C::a;
const int C::b;

Or just use the enum hack that was used to accomodate older compilers (but which may after all be the only legal way):

class C {
  public:
    enum { a = 0, b = 1 };
};


See 9.4.2/4:

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 within its scope. 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.

There is some contention (I believe) as to the precise meaning of "used" although my understanding is roughly that the if program requires the address of the variable then it's "used" in this context. It doesn't seem unreasonable in my mind at all that changing the ternary to an if/else or changing optimization level could change the view of the program as seen by g++ thus causing the failure or success. Also note that it doesn't say anything about a required diagnostic if you violate the requirement here.

You can't go wrong by always defining your static members.


Try defining it globally without optimisation.

const int C::a = 0; 


change the following line return somefunc() ? C::a : C::b;

to return (somefunc() ? C::a : C::b);

It should compile.

0

精彩评论

暂无评论...
验证码 换一张
取 消