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

Почему статические константные члены не могут появляться в постоянном выражении типа "switch"

У меня есть следующее объявление некоторых статических константных элементов

.h

class MyClass : public MyBase
{
public:
    static const unsigned char sInvalid;
    static const unsigned char sOutside;
    static const unsigned char sInside;
    //(41 more ...)
}

.cpp

const unsigned char MyClass::sInvalid = 0;
const unsigned char MyClass::sOutside = 1;
const unsigned char MyClass::sInside = 2;
//and so on

В какой-то момент я хочу использовать это значение в коммутаторе, например:

unsigned char value;
...
switch(value) {
    case MyClass::sInvalid : /*Do some ;*/ break;
    case MyClass::sOutside : /*Do some ;*/ break;
    ...
}

Но я получаю следующую ошибку компилятора: ошибка: "MyClass:: sInvalid" не может появляться в константном выражении.

Я прочитал другой файл switch-can not-seem-constant-stuff и не нашел ответа для меня, так как не понимаю, почему те static const unsigned char не являются постоянным выражением.

Я использую gcc 4.5.

4b9b3361

Ответ 1

Проблемы, которые вы видите, связаны с тем, что этот

static const unsigned char sInvalid;

не может быть выражением постоянной времени компиляции, поскольку компилятор не знает его значения. Инициализируйте их в заголовке следующим образом:

class MyClass : public MyBase
{
public:
    static const unsigned char sInvalid = 0;
    ...

и он будет работать.

Ответ 2

Значения действительно const, но они не являются константами времени компиляции.

A switch условие разрешено во время компиляции, а не во время выполнения. Вы можете инициализировать sInvalid до любого значения, если только один раз, а switch никогда не узнает об этом до времени выполнения.

Кажется, что вам лучше использовать enum вместо констант static. Помимо того, что он будет работать, он кажется более подходящим по дизайну.

Ответ 3

Вы можете использовать трюк перечисления, чтобы сделать их константами времени компиляции:

class MyClass 
{
public:
    enum {
        sInvalid,
        sOutside,
        sInside,
        //(41 more ...)
    };
};

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

int main(int argc, char *argv[])
{
    unsigned char buf[32];
    buf[0] = MyClass::sInvalid; //int to unsigned char
    return buf[0]; //Cast back to int (and avoid a warning a -Wall)
}

И используйте MyClass::sInvalid в ваших инструкциях swith.