【问题标题】:If there's an if-constexpr, how come there's no switch-constexpr?如果有 if-constexpr,怎么没有 switch-constexpr?
【发布时间】:2019-04-22 01:53:57
【问题描述】:

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

【问题讨论】:

    标签: c++ c++17 c++20 if-constexpr


    【解决方案1】:

    if constexpr 最终派生自 more sane form 的 static if concept。由于这种推导,标准委员会似乎没有考虑将相同的想法应用于switch。所以这可能是主要原因:没有人将它添加到论文中,因为它是一种受限制的语法形式,switch 没有意义。

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

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

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

    是的,如果不在标签之间放置 break; 语句,可能会导致编译错误。

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

    【讨论】:

    • 虽然这两个提议都很有趣,但 P1308 引入的语法看起来很像当前的 C++。 P2160 是一篇非常吸引人的论文。
    • @JonHarper:“P1308 引入的语法看起来与当前的 C++ 非常相似。”你知道,通常我会回答“你说这好像是件坏事;)”。但是看了那个提案之后,里面有点吓人。
    • 优秀的解释和参考。 Haskell++,有人吗?
    • @NicolBolas [.scary true]
    【解决方案2】:

    我不权威,但如果你看selection statementsif有明确的真假区分,switch没有。

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

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

    【讨论】:

    • 我确信有一种简单的方法可以将任何switch 转换为if 分支的树,即使考虑失败。
    • 查看 Duff 的设备。 switch 没有大多数人想象的那么有条理。
    • @T.C.我不确定你在评论谁,我的回答还是第一条评论,但这正是我的观点。由于缺乏这种结构,因此很难重新实现它。将丢弃规则建立在整个语句的基础上——使用现有的语法,比为无定形的东西提出自定义规则要容易得多。
    【解决方案3】:

    考虑以下来自the answer to another question 的示例(关于优化的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 的一种原因:比较类型或其他不仅仅是一组值的东西。所以switch constexpr 对我来说没有多大意义。如果有的话,它需要另一种语法(有点像我的例子),我不确定它是否有益。这当然没有必要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-12
      • 1970-01-01
      • 2016-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多