Dollarslice
Dollarslice

Reputation: 10314

Case expression not constant

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.

Upvotes: 24

Views: 63538

Answers (5)

std::map + C++11 lambdas workaround

This method allows for non constants, should give us O(1) amortized What is the best way to use a HashMap in 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;
}

Possible output:

1 0
2 1
0 2

For usage from inside a class, don't forget to build the map statically as shown at: Why switch statement cannot be applied on strings?

Upvotes: 1

Sebastian Mach
Sebastian Mach

Reputation: 39099

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;, making x a read-only copy of the value y had at the time of initialization.

With a modern compiler, you can either use enums or 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: ;
    }
}

Upvotes: 5

R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234584

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.

If you declare:

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.

Upvotes: 2

AnT stands with Russia
AnT stands with Russia

Reputation: 320631

Constants used in case labels must be integral constant expressions. An integral constant expression 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.

Upvotes: 1

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361612

The case statements require integral value which must be known at compile-time, which is what is meant by constant here. But the const members of a class are not really constant 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;
};

Upvotes: 22

Related Questions