切换constexpr功能

0Ho*_*Tea 4 c++ constexpr c++14 c++17

Wiki中找到以下声明:

C++ 11引入了constexpr声明函数的概念; 一个可以在编译时执行的函数.它们的返回值可能由需要常量表达式的操作使用,例如整数模板参数.但是,C++ 11 constexpr函数只能包含一个返回的表达式(以及static_asserts和少量其他声明).

C++ 14放宽了这些限制.Constexpr声明的函数现在可以包含以下内容:条件

  • ...
  • 分支声明ifswitch

那么,实际上是否可以在c ++ 14/c ++ 17中的constexpr函数中进行切换?而且,如果可能的话,那是什么语法?例如,我想要这样的东西:

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;
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

Jes*_*seC 24

不完全是。在 的情况下if constexpr,您可以放心,生成的代码没有分支。此外,丢弃的语句不需要编译。这些是我认为您期望从 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
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,对于 Baum 接受的答案,我有点挑剔,这对于实际目的来说很好。我怀疑你会发现好的编译器会从带有 constexpr 函数的 switch-case 语句中删除逻辑上不可能的位,甚至是非 constexpr 内联函数。


Bau*_*gen 13

那么,实际上是否可以在c ++ 14/c ++ 17中的constexpr函数中进行切换?

是.

而且,如果可能的话,那是什么语法?

语法绝对没有什么特别之处,这只是一个普通的问题switch.像这样:

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

int main () {
    int arr[fun(3)];
}
Run Code Online (Sandbox Code Playgroud)