11

Found the following statement in Wiki:

C++11 introduced the concept of a constexpr-declared function; a function which could be executed at compile time. Their return values could be consumed by operations that require constant expressions, such as an integer template argument. However, C++11 constexpr functions could only contain a single expression that is returned (as well as static_asserts and a small number of other declarations).

C++14 relaxes these restrictions. Constexpr-declared functions may now contain the following: The conditional

  • ...
  • branching statements if and switch

So, Is it actually possible to have a switch in a constexpr function in c++14/c++17? And, if possible, what syntax is for that? For example, I'd like to have something like this:

enum class Terrain : std::uintmax_t {
    ROAD,
    SOIL,
    GRASS,
    MUD,
    SNOW,
};

constexpr float
getStepPrice(Terrain const& terrain)
{
    switch constexpr (terrain)
    {
        case Terrain::ROAD: return 1.0f;
        ...
    }
}
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182

2 Answers2

27

Not exactly. In the case of if constexpr, you can rest assured that the resulting code has no branching. Moreover, discarded statements need not compile. Those are the guarantees I think you would expect from a true switch constexpr.

class Dog;
class Snake;

#define USE_IF

template<typename Pet>
constexpr void foo(Pet pet) {
#ifdef USE_IF
    // This works
    if constexpr(std::is_same_v<Pet, Dog>)   pet.bark();
    else                                     pet.slither();
#else
    // This doesn't
    switch (std::is_same_v<Pet, Dog>) {
        case true:  pet.bark();    break;  // <== Error if Snake
        case false: pet.slither(); break;  // <== Error if Dog
    }
#else
}

BTW, I'm being a little nit-picky vis-a-vis Baum's accepted answer, which is fine, for practical puposes. I suspect you'd find good compilers will elide logically impossible bits from a switch-case statement with constexpr functions, as well as even non-constexpr inlined functions.

JesseC
  • 432
  • 4
  • 5
21

So, Is it actually possible to have a switch in a constexpr function in c++14/c++17?

Yes.

And, if possible, what syntax is for that?

There is absolutely nothing special about the syntax, it's just a normal switch. Like this:

constexpr int fun (int i) {
    switch(i) {
        case 0: return 7;
        default: return 5;
    }
}

int main () {
    int arr[fun(3)];
}
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • 1
    Not that a static switch (just like a static loop) wouldn't be nice to have. A library-solution has some significant drawbacks. – Deduplicator Jun 25 '19 at 20:16