V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ChaosesIb
V2EX  ›  C++

有关模板 + if constexpr + static_assert 的问题

  •  
  •   ChaosesIb ·
    Chaoses-Ib · 141 天前 · 940 次点击
    这是一个创建于 141 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码:

    template<typename T=void>
    void f() {
        if constexpr(false) {
            static_assert(false, "fail");
        }
    }
    
    int main()
    {
        f<>();
    }
    

    编译结果:
    s1.ax1x.com/2022/03/20/qVrfoj.png
    godbolt.org/z/GMnKc59E9

    为什么同一版本 MSVC 下 C++17 可以编译成功,而 C++20 和 GCC C++17 都不行?是因为 C++17 里这是 UB 吗?

    没查到相关资料,C++20 的变更说明里似乎也没有。

    GeruzoniAnsasu
        1
    GeruzoniAnsasu  
       141 天前   ❤️ 1
    https://stackoverflow.com/questions/50051473/if-constexpr-in-c17-does-not-work-in-a-non-templated-function
    https://www.v2ex.com/t/815172#reply10

    照上次获得的经验来看,这里应该已经是模板实例化的阶段,所以 GCC 的行为是对的。也许 MSVC 又做了什么非标准流程,无法深究了
    pragmatwice
        2
    pragmatwice  
       141 天前   ❤️ 1
    GCC 在这里的行为是正确的,如果想达到预期的效果可以加入一个 dependent name 以延迟 static_assert 的 evaluate ,例如

    ```c++
    template <typename T> constexpr const auto always_false = false;

    template<typename T=void>
    void f() {
    if constexpr(false) {
    static_assert(always_false<T>, "fail");
    }
    }

    int main()
    {
    f<>();
    }
    ```
    ChaosesIb
        3
    ChaosesIb  
    OP
       137 天前
    @pragmatwice 谢谢

    在 SO 上也查到了另外两种 workaround:
    ```cpp
    static_assert(!sizeof(T*), "fail");
    ```

    ```cpp
    // C++20
    []<bool false_value = false>() {
    static_assert(false_value, "fail");
    }();
    ```

    不过还是挺好奇为什么 MSVC 会在 17 和 20 间行为不一致,也许是实现 20 的时候没有复用,而是又写了一遍相关处理吧
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2896 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 655ms · UTC 11:19 · PVG 19:19 · LAX 04:19 · JFK 07:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.