Expresión de caso no constante

I am getting a 'case expression not constant' error in a switch statement. However, the header provides a definition for the used constants, and the constructor provides initialisation for them in its initialization list.

Additionally, when I mouse over the "problem" statements it identifies them as constants.

const int ThisClass::EXAMPLE_CONSTANT

error expression must have a constant value

This seems a little counter-intuitive to me. I did some research and found a similar problem that someone else had. They were told that all constants must in fact be initialised in 'main' and that this was a limitation of the language. Is this really the case? It seems unlikely.

preguntado el 08 de noviembre de 11 a las 11:11

provide actual code that demonstrates the problem. What you pasted is not really helpful. -

What compiler are you using? Is it really C++? -

5 Respuestas

La Certificación de Catequista de case statements require integral value which must be known at compile-time, which is what is meant by constante here. But the const members of a clase no son realmente constante in that sense. They're are simply read-only.

Instead of fields, you can use enum :

class ThisClass
{
    public:

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

And then you can write,

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

respondido 08 nov., 11:15

if the constants are not related, I'd propose to use an unnamed enum. - Sebastián Mach

You need a "real" compile time integer constant. const in C++ means read-only, and a const variable can be initialized just like int y = 0; const int x = y;, Haciendo x a read-only copy of the value y had at the time of initialization.

With a modern compiler, you can either use enums o constexprs to store (integral) members of compile-time-constness:

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

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

respondido 08 nov., 11:16

constexpr doesn't make the member static. - R. Martinho Fernandes

This is a bit of a mess. In C++ const can be used for several things, like declaring actual constants, and declaring read-only variables.

Si declara:

const int x = 0;

In global, namespace, or local scope, it is a constant. You can use it where constant expressions are required (like case labels or array sizes). However, at class scope or as a function parameter, it's just a read-only variable.

Additionally, if you declare at class scope:

static const int x = 0;

This is also a constant.

respondido 08 nov., 11:16

A const int variable declared in function scope (i.e in local scope) and initialized with an integral constant expression does itself form integral constant expressions in C++. So in function scope it is not just a "read-only variable". - Hormiga

@AndreyT oops, I meant function parameter :) Thanks. - R. Martinho Fernandes

Constants used in case labels must be integral constant expressions. Un expresión constante integral must satisfy a much more strict set of requirements than just being an integral object declared as const.

A non-static class member cannot be used in an integral constant expression, so what you are trying to do will not compile. A static class member, for example, can be used in an integral constant expression if its initializer is "visible" at the point of use.

respondido 08 nov., 11:15

std::map + C++11 lambdas workaround

This method allows for non constants, should give us O(1) amortizado ¿Cuál es la mejor forma de utilizar un HashMap en C ++? :

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

Salida posible:

1 0
2 1
0 2

For usage from inside a class, don't forget to build the map statically as shown at: ¿Por qué la instrucción de cambio no se puede aplicar a las cadenas?

Respondido el 15 de enero de 18 a las 18:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.