Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined Reference in inline function, solved with unary +

I have a strange gcc 4.7 problem with c++11 enabled :

When I want to compile this:

constexpr unsigned int getDim(const int e){
        return (e==1)?  A::Set::Dimension :
            (
              (e==2)? B::Set::Dimension :

                (
                    (e==3)? C::Set::Dimension :
                    (
                       +D::Set::Dimension

                    )
                )
            );
 }

where for each struct A,B,C,D a typedef for Set is defined where the related Set has an int Dimension, for example

struct SetOne{
   static const int Dimension = 1;
}

struct A{
   typedef SetOne Set;
}

If I don't use the unary + infront of D::Set::Dimension the linker fails complaining about undefined references to SetOne::Dimension.

Is this the same problem as: Undefined reference to static class member

I cannot give a MWE as the problem vanished for a simple example with one .cpp file. ? (but all definitions are for A,B,C,D are in one header file)

Does anybody have a clue what might go wrong here? This is unintuitiv :-)

Observation 2: If one replaces: +D::Set::Dimension with 0, it compiles fine, but why the hack the other statements as A::Set::Dimension do not rise the same linking error?

like image 229
Gabriel Avatar asked Feb 14 '23 13:02

Gabriel


1 Answers

In the expression you are building, the ternary expression is yielding an lvalue, which causes the odr-use of the static constant. The One Definition Rule requires that all static members that are odr-used are defined, so you need to provide a definition (in a single translation unit).

So why does the problem go away with the unary +?

The unary + does not cause the odr-use of the static member, it only requires an rvalue, and the result of it is another rvalue. That cascades out through the conditional operators as once one of the two arguments is an rvalue the result of the expression will also be an rvalue. The end result is that the single + has the effect of forcing the lvalue-to-rvalue conversion of all of the static consts used in the function and removes the odr-uses.

If one replaces: +D::Set::Dimension with 0, it compiles fine

Again, 0 is an rvalue, and it will have the same effect as the unary + described above.

like image 57
David Rodríguez - dribeas Avatar answered Feb 16 '23 01:02

David Rodríguez - dribeas