切换constexpr函数

时间:2017-08-06 16:57:30

标签: c++ c++14 constexpr 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;
        ...
    }
}

2 个答案:

答案 0 :(得分:12)

  

那么,实际上是否可以在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)];
}

答案 1 :(得分:1)

不完全是。对于if constexpr,您可以放心,结果代码没有分支。此外,丢弃的语句无需编译。这些是我认为您会从真正的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
}

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