Подтвердить что ты не робот

Этот код сломан или есть ошибка в g++?

По какой-то странной причине g++ (версии 4.5.0 и 4.5.2) не может скомпилировать этот код:

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;
}

Это дает мне эту ошибку:

/tmp/ccyvvTUy.o:/home/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

Что странно, если я сменил проблемную строку на прокомментированную строку, которую она компилирует. Это что-то не так с моим кодом и что-то, что я не понимаю о С++, или это просто ошибка в g++?

4b9b3361

Ответ 1

Существует текущая дискуссия о том, действительно ли этот код является законным или нет.

В любом случае, согласно некоторым показаниям, константы действительно должны быть определены до использования, а не только объявлены. То есть

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

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

Или просто используйте хакеры enum, которые использовались для размещения старых компиляторов (но которые могут быть единственным законным способом):

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

Ответ 2

См. 9.4.2/4:

Если статический член данных имеет const-константу или const-перечисление type, его объявление в определении класса может указывать константу инициализатор, который должен быть интегральным постоянным выражением (5.19). В в этом случае член может фигурировать в интегральных постоянных выражениях в пределах его объема. Член все еще должен быть определен в пространстве имен область применения, если она используется в программе и определение области пространства имен не должен содержать инициализатор.

Существует некоторое утверждение (я считаю) относительно точного значения "используемого", хотя мое понимание примерно таково, что программа if требует адрес переменной, а затем "используется" в этом контексте. В моем сознании вообще не кажется необоснованным, что изменение троичного на if/else или изменение уровня оптимизации может изменить вид программы, как видно из g++, что приведет к сбою или успеху. Также обратите внимание, что он ничего не говорит о необходимой диагностике, если вы нарушите это требование здесь.

Вы не можете ошибаться, всегда определяя свои статические члены.

Ответ 3

Попробуйте определить его глобально без оптимизации.

const int C::a = 0; 

Ответ 4

измените следующую строку    return somefunc()? C:: a: C:: b;

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

Он должен скомпилироваться.