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

2022-03-20 02:58:15 +08:00
 ChaosesIb

代码:

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 的变更说明里似乎也没有。

1583 次点击
所在节点    C++
3 条回复
GeruzoniAnsasu
2022-03-20 03:17:27 +08:00
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
2022-03-20 13:42:58 +08:00
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
2022-03-24 00:41:15 +08:00
@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 的时候没有复用,而是又写了一遍相关处理吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/841566

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX