Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.)

like image 329
Evan Kroske Avatar asked Mar 26 '11 23:03

Evan Kroske


People also ask

Is ternary operator better than if else?

Moreover, as has been pointed out, at the byte code level there's really no difference between the ternary operator and if-then-else. As in the above example, the decision on which to choose is based wholly on readability.

Is ternary faster than if else C?

It is not faster. There is one difference when you can initialize a constant variable depending on some expression: const int x = (a<b) ?

What is the advantage of ternary operator over if else statement?

Advantages of Ternary Operator It will improve the readability of the code. The code becomes more straightforward. Makes basic if/else logic easier to code. Instead of breaking your output building for if/else statements,you can do your if/else logic in line with output.

What are the three arguments of a ternary operator?

The ternary operator take three arguments: The first is a comparison argument. The second is the result upon a true comparison. The third is the result upon a false comparison.


2 Answers

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;
like image 64
Johannes Schaub - litb Avatar answered Sep 25 '22 01:09

Johannes Schaub - litb


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 
    };
};
like image 34
James McNellis Avatar answered Sep 24 '22 01:09

James McNellis