Случайное выражение не постоянное

Я получаю ошибку "case expression not constant" в инструкции switch. Однако заголовок предоставляет определение для используемых констант, а конструктор обеспечивает инициализацию для них в своем списке инициализации.

Кроме того, когда я нажимаю на "проблемные" операторы, он идентифицирует их как константы.

const int ThisClass::EXAMPLE_CONSTANT

error expression must have a constant value

Это кажется мне немного контр-интуитивным. Я сделал некоторые исследования и нашел аналогичную проблему, что кто-то еще. Им сказали, что все константы на самом деле должны быть инициализированы в "главном" и что это ограничение языка. Это действительно так? Это кажется маловероятным.

Ответы

Ответ 1

Операторы case требуют целочисленного значения, которое должно быть известно во время компиляции, что и подразумевается под константой здесь. Но члены класса const не очень постоянны в этом смысле. Они просто доступны только для чтения.

Вместо полей вы можете использовать enum:

class ThisClass
{
    public:

        enum Constants
        {
            EXAMPLE_CONSTANT = 10,
            ANOTHER_CONSTANT = 20
        };    
};

А затем вы можете написать

switch(c)
{
      case ThisClass::EXAMPLE_CONSTANT:
                   //code
                   break;
      case ThisClass::ANOTHER_CONSTANT:
                   //code
                   break;
};

Ответ 2

Вам нужна "реальная" константа целочисленного времени компиляции. const в С++ означает только для чтения, а переменная const может инициализироваться так же, как int y = 0; const int x = y;, делая x только для чтения значение y, имеющееся только для чтения, во время инициализации.

С помощью современного компилятора вы можете использовать enum или constexpr для хранения (интегральных) элементов времени компиляции:

class Foo {
public:
    static constexpr int x = 0;
    enum { y = 1 };
};

int main () {
    switch (0) {
    case Foo::x: ;
    case Foo::y: ;
    }
}

Ответ 3

Константы, используемые в методах case, должны быть неотъемлемыми постоянными выражениями. Интегральное константное выражение должно удовлетворять гораздо более строгим требованиям, чем просто интегральный объект, объявленный как const.

Нестатический член класса не может использоваться в интегральном постоянном выражении, поэтому то, что вы пытаетесь сделать, не будет компилироваться. Например, статический член класса может использоваться в интегральном постоянном выражении, если его инициализатор является "видимым" в точке использования.

Ответ 4

Это немного беспорядок. В С++ const можно использовать для нескольких вещей, таких как объявление реальных констант и объявление переменных только для чтения.

Если вы заявляете:

const int x = 0;

В глобальном, пространстве имен или локальной области это константа. Вы можете использовать его там, где требуются постоянные выражения (например, метки меток или размеры массива). Однако в классе или в качестве параметра функции это просто переменная только для чтения.

Кроме того, если вы объявляете в области класса:

static const int x = 0;

Это также константа.

Ответ 5

std::map + С++ 11 обходной путь lambdas

Этот метод допускает не константы, должен дать нам O(1) amortized Каков наилучший способ использования HashMap в С++?:

#include <ctime>
#include <functional>
#include <unordered_map>
#include <iostream>

int main() {
    int result;
    int key0 = std::time(NULL) % 3;
    int key1 = (key0 + 1) % 3;
    int key2 = (key0 + 2) % 3;
    std::unordered_map<int,std::function<void()>> m{
        {key0, [&](){ result = 0; }},
        {key1, [&](){ result = 1; }},
        {key2, [&](){ result = 2; }},
    };
    m[key0]();
    std::cout << key0 << " " << result << std::endl;
    m[key1]();
    std::cout << key1 << " " << result << std::endl;
    m[key2]();
    std::cout << key2 << " " << result << std::endl;
}

Возможный выход:

1 0
2 1
0 2

Для использования внутри класса не забудьте создать карту статически, как показано на рисунке: Почему оператор switch не может применяться к строкам?