如果有 if-constexpr,为什么没有 switch-constexpr?
If there's an if-constexpr, how come there's no switch-constexpr?
在 C++17 中,if constexpr
was introduced; however, there doesn't seem to be a switch constexpr
(see here)。这是为什么?也就是说,如果编译器支持 if constexpr
,那么它支持 switch constexpr
是否也不是微不足道的(最坏的情况是作为一个 if-then-else-if-etc. 链,或者带有一些标志的多个 if控制掉落)?
我不是权威,但是如果你看一下selection statements if
有明显的真假区分,switch
没有。
我认为从评估中丢弃 switch 未使用的部分会相对困难一些,尤其是因为它们可能会失败。
如果您想保持 switch
的所有(奇异)功能,将 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{});
你不能用开关复制它,因为你需要 case 值实际上是类型;类似下面的内容,由于显而易见的原因,这是不可能的。
template <typename T>
void pet(T x)
{
switch (T) {
case Cat:
x.meow();
break;
case Dog:
x.meow();
break;
}
}
此示例是 if constexpr
的某种原因:比较类型或其他不仅仅是一组值的事物。所以 switch constexpr
对我来说没有多大意义。如果有的话,它需要另一种语法(有点像我的例子),我不确定它是否有用。确实没必要。
if constexpr
was ultimately derived from a more sane form of the static if
concept。由于这种推导,标准委员会似乎没有考虑将相同的想法应用于 switch
。所以这可能是主要原因:没有人将它添加到论文中,因为它是一种语法的限制形式,其中 switch
没有意义。
话虽这么说,switch
有很多包袱。最值得注意的一点是自动 fallthrough 行为。这使得定义其行为有点问题。
看,if constexpr
的强大功能之一是在某些条件下可以丢弃编译时未采用的一侧。这是语法的重要部分。因此,假设的 switch constexpr
应该具有类似的权力。
这对于 fallthrough 来说要难得多,因为 case
块不像 if
语句的两个块那样根本不同。特别是如果你有条件失败。现在,您可以使 switch constexpr
没有自动 fallthrough(或根本没有 fallthrough),以便不同的部分是不同的。但是你已经巧妙地改变了语法的工作方式; switch
的非 constexpr
形式与 constexpr
形式的行为不同。这样不好。
是的,如果不在标签之间放置 break;
语句,可能会导致编译错误。
请注意,两个主要的模式匹配建议 P1308 and P1260,特别是 避免 使用 switch
,而是发明一个新关键字。他们都有 constexpr
个方面,但他们非常清楚地表明他们不是 switch/case
。
在 C++17 中,if constexpr
was introduced; however, there doesn't seem to be a switch constexpr
(see here)。这是为什么?也就是说,如果编译器支持 if constexpr
,那么它支持 switch constexpr
是否也不是微不足道的(最坏的情况是作为一个 if-then-else-if-etc. 链,或者带有一些标志的多个 if控制掉落)?
我不是权威,但是如果你看一下selection statements if
有明显的真假区分,switch
没有。
我认为从评估中丢弃 switch 未使用的部分会相对困难一些,尤其是因为它们可能会失败。
如果您想保持 switch
的所有(奇异)功能,将 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{});
你不能用开关复制它,因为你需要 case 值实际上是类型;类似下面的内容,由于显而易见的原因,这是不可能的。
template <typename T>
void pet(T x)
{
switch (T) {
case Cat:
x.meow();
break;
case Dog:
x.meow();
break;
}
}
此示例是 if constexpr
的某种原因:比较类型或其他不仅仅是一组值的事物。所以 switch constexpr
对我来说没有多大意义。如果有的话,它需要另一种语法(有点像我的例子),我不确定它是否有用。确实没必要。
if constexpr
was ultimately derived from a more sane form of the static if
concept。由于这种推导,标准委员会似乎没有考虑将相同的想法应用于 switch
。所以这可能是主要原因:没有人将它添加到论文中,因为它是一种语法的限制形式,其中 switch
没有意义。
话虽这么说,switch
有很多包袱。最值得注意的一点是自动 fallthrough 行为。这使得定义其行为有点问题。
看,if constexpr
的强大功能之一是在某些条件下可以丢弃编译时未采用的一侧。这是语法的重要部分。因此,假设的 switch constexpr
应该具有类似的权力。
这对于 fallthrough 来说要难得多,因为 case
块不像 if
语句的两个块那样根本不同。特别是如果你有条件失败。现在,您可以使 switch constexpr
没有自动 fallthrough(或根本没有 fallthrough),以便不同的部分是不同的。但是你已经巧妙地改变了语法的工作方式; switch
的非 constexpr
形式与 constexpr
形式的行为不同。这样不好。
是的,如果不在标签之间放置 break;
语句,可能会导致编译错误。
请注意,两个主要的模式匹配建议 P1308 and P1260,特别是 避免 使用 switch
,而是发明一个新关键字。他们都有 constexpr
个方面,但他们非常清楚地表明他们不是 switch/case
。