在 C++17if constexpr
中引入;但是,似乎没有switch constexpr
(请参见此处)。这是为什么?也就是说,如果编译器支持if constexpr
,它是否支持也不是微不足道的switch constexpr
(最坏的情况是 if-then-else-if-etc. 链,或者多个 if 带有一些标志来控制失败)?
3 回答
if constexpr
最终是从一个更理智的static if
概念中衍生出来的。由于这种推导,switch
标准委员会似乎没有考虑过应用相同的想法。所以这可能是主要原因:没有人将它添加到论文中,因为它是一种switch
没有意义的受限语法形式。
话虽如此,switch
里面有很多包袱。最值得注意的一点是自动失败行为。这使得定义它的行为有点问题。
看, 的力量之一if constexpr
是在某些条件下使编译时未采取的一侧被丢弃。这是语法的重要组成部分。因此,假设假设switch constexpr
具有类似的权力。
这对于 fallthrough 来说要困难得多,因为这些case
块并不像if
语句的两个块那样根本不同。特别是如果您有条件失败。现在,您可以switch constexpr
不设置自动回落(或根本不回落),以便不同的部分是不同的。但是你已经巧妙地改变了语法的工作方式;非constexpr
形式的switch
行为与constexpr
形式不同。这不好。
是的,您可以将不在break;
标签之间放置语句的编译错误。
请注意,两个主要的模式匹配建议P1308和P1260专门避免使用switch
,而是发明了一个新关键字。他们都有自己的constexpr
方面,但他们非常清楚地表明他们不是switch/case
。
我不权威,但如果你看选择语句 if
有明确区分真假语句,switch
不会。
我认为从评估中丢弃未使用的 switch 部分会相对困难,特别是因为它们可能会失败。
如果您想保持它的所有(外来)功能,那么重新实现 as 并不是那么简单switch
。if-else-if
从另一个问题(关于优化if
分支)的答案中考虑以下示例。
struct Cat { void meow() { } };
struct Dog { void bark() { } };
template <typename T>
void pet(T x)
{
if(std::is_same<T, Cat>{}){ x.meow(); }
else if(std::is_same<T, Dog>{}){ x.bark(); }
}
pet(Cat{});
pet(Dog{});
你不能用 switch 来复制它,因为你需要 case 值实际上是类型;类似于以下内容,由于显而易见的原因,这是不可能的。
template <typename T>
void pet(T x)
{
switch (T) {
case Cat:
x.meow();
break;
case Dog:
x.meow();
break;
}
}
这个例子的原因是if constexpr
:比较类型或其他不仅仅是一组值的东西。所以 aswitch constexpr
对我来说没有多大意义。如果有的话,它需要另一种语法(有点像我的例子),我不确定它是否有益。这当然没有必要。