在Wiki中找到以下声明:
C ++ 11引入了constexpr声明函数的概念;一个 可以在编译时执行的函数。他们的回报价值 可以由需要常量表达式的操作消耗, 例如整数模板参数。但是,C ++ 11 constexpr 函数只能包含一个返回的表达式(如 以及static_asserts和少量其他声明)。
C ++ 14放宽了这些限制。 Constexpr声明的函数现在可以 包含以下内容:条件
- ...
- 分支语句
if
和switch
那么,实际上是否可以在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;
...
}
}
答案 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语句中排除掉逻辑上不可能的位。