代码:
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 的变更说明里似乎也没有。
1
GeruzoniAnsasu 2022-03-20 03:17:27 +08:00 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 又做了什么非标准流程,无法深究了 |
2
pragmatwice 2022-03-20 13:42:58 +08:00 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<>(); } ``` |
3
ChaosesIb OP @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 的时候没有复用,而是又写了一遍相关处理吧 |