开发者

Why don't static member variables play well with the ternary operator?

Here's the deal. I have a static class which contains several static functions used for getting input. The class contains a private static member variable for indicating whether the user entered any information. Each input method checks to see whether the user entered any information, and sets the status variable accordingly. I think this would be a good time to use the ternary operator. Unfortunately, I can't, because the compiler doesn't like that.

I replicated the problem, then simplified my code as much as was possible to make it easy to understand. This is not my original code.

Here's my header file:

#include <iostream>

using namespace std;

class Test {
public:
    void go ();
private:
    static const int GOOD = 0;
    static const int BAD = 1;
};

Here's my implementation with the ternary operator:

#include "test.h"

void Test::go () {
  开发者_如何转开发  int num = 3;
    int localStatus;
    localStatus = (num > 2) ? GOOD : BAD;
}

Here's main function:

#include <iostream>
#include "test.h"

using namespace std;

int main () {
    Test test = Test();
    test.go();
    return 0;
}

When I try to compile this, I get this error message:

test.o: In function `Test::go()':
test.cpp:(.text+0x17): undefined reference to `Test::GOOD'
test.cpp:(.text+0x1f): undefined reference to `Test::BAD'
collect2: ld returned 1 exit status

However, if I replace this:

localStatus = (num > 2) ? GOOD : BAD;

with this:

if (num > 2) {
    localStatus = GOOD;
} else {
    localStatus = BAD;
}

The code compiles and runs as expected. What obscure C++ rule or GCC corner case is responsible for this lunacy? (I'm using GCC 4.4.1 on Ubuntu 9.10.)


This is according to the C++ Standard. The ternary operator does constitute a single lvalue that will refer to either GOOD or BAD at runtime. The lvalue to rvalue conversion is not applied immediately to either the lvalue GOOD or BAD, and therefor you require a definition of GOOD and BAD.

See the core language issue report http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#712 .

As a workaround, you can apply explicit casts to int (which reads their values, thereby doing an lvalue to rvalue conversion) or use an operator that reads the value, like +:

localStatus = (num > 2) ? +GOOD : +BAD;


class Test {
    static const int GOOD = 0;
    static const int BAD = 1;
};

These are only declarations; they are not definitions. You need to provide definitions of the static member variables, outside of the definition of the class, in one of your .cpp files:

const int Test::GOOD;
const int Test::BAD;

Alternatively, for integer constants, it is often more convenient to use an enum:

class Test {
    enum { 
        GOOD = 0,
        BAD = 1 
    };
};


Your code looks fine to me. And ideone agrees: see this link. But that's with gcc-4.3.4. However, my gcc-4.4.0 doesn't accept it. So whatever the reason, it's not obvious.

Edited to add: The following variant compiles under gcc-4.4.0:

int localStatus = 42 ? GOOD : BAD;

Reminder: the following code doesn't compile:

int localStatus = (num == 42) ? GOOD : BAD;

So somebody has screwed up somewhere.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜