11

在 C++17if constexpr中引入;但是,似乎没有switch constexpr(请参见此处)。这是为什么?也就是说,如果编译器支持if constexpr,它是否支持也不是微不足道的switch constexpr(最坏的情况是 if-then-else-if-etc. 链,或者多个 if 带有一些标志来控制失败)?

4

3 回答 3

21

if constexpr最终是从一个更理智static if概念中衍生出来的。由于这种推导,switch标准委员会似乎没有考虑过应用相同的想法。所以这可能是主要原因:没有人将它添加到论文中,因为它是一种switch没有意义的受限语法形式。

话虽如此,switch里面有很多包袱。最值得注意的一点是自动失败行为。这使得定义它的行为有点问题。

看, 的力量之一if constexpr是在某些条件下使编译时未采取的一侧被丢弃。这是语法的重要组成部分。因此,假设假设switch constexpr具有类似的权力。

这对于 fallthrough 来说要困难得多,因为这些case块并不像if语句的两个块那样根本不同。特别是如果您有条件失败。现在,您可以switch constexpr不设置自动回落(或根本不回落),以便不同的部分是不同的。但是你已经巧妙地改变了语法的工作方式;非constexpr形式的switch行为与constexpr形式不同。这不好。

是的,您可以将不在break;标签之间放置语句的编译错误。

请注意,两个主要的模式匹配建议P1308P1260专门避免使用switch,而是发明了一个新关键字。他们都有自己的constexpr方面,但他们非常清楚地表明他们不是switch/case

于 2018-11-19T17:29:03.613 回答
0

我不权威,但如果你看选择语句 if有明确区分真假语句,switch不会。

我认为从评估中丢弃未使用的 switch 部分会相对困难,特别是因为它们可能会失败。

如果您想保持它的所有(外来)功能,那么重新实现 as 并不是那么简单switchif-else-if

于 2018-11-19T17:11:22.050 回答
0

从另一个问题(关于优化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对我来说没有多大意义。如果有的话,它需要另一种语法(有点像我的例子),我不确定它是否有益。这当然没有必要。

于 2018-11-19T17:14:09.183 回答