Constexpr 和模板:编译器错误?
Constexpr and templates: compiler bug?
以下按预期工作:
#include <array>
constexpr std::array<int, 3> values = {1, 2, 3};
template <int i> struct A { static constexpr int val = values[i]; };
int main() { A<1> a; }
但是,如果我们使用 values.size()
作为模板参数,我会从 MSVC 编译器收到编译器错误:
int main() { A<values.size()> a; }
错误是表达式未计算为常量。 GCC 编译没有错误。
- 这是 MSVC 编译器的错误吗?
- 是否有 standard/clever 解决方法来规避此错误?
这实际上是 bug/flaw GCC,而不是 MSVC。
A<values.size()> a;
导致您访问 values
超出范围,因为有效索引是 [0, size())
。 MSVC 给你一个错误,它不能这样做,因为它是未定义的行为,并且在常量表达式中不允许这样做。
请注意,clang 也会正确诊断并发出错误:https://godbolt.org/z/vmi86S
MSVC 是对的。在任何 constexpr 上下文中都不能有未定义的行为。否则这不是常量表达式。
行:
int main() { A<values.size()> a; }
基本上是:
constexpr auto i = values[values.size()];
这是越界的。事实上,MSVC 正确诊断错误:
example.cpp
<source>(3): error C2131: expression did not evaluate to a constant
C:/msvc/v19_16/include\array(187): note: failure was caused by out of range index 3; allowed range is 0 <= index < 3
<source>(4): note: see reference to class template instantiation 'A<3>' being compiled
<source>(2): note: see reference to class template instantiation 'std::array<int,3>' being compiled
Compiler returned: 2
另一方面,GCC 和 MSVC 都接受此代码:
int main() { A<values.size() - 1> a; }
以下按预期工作:
#include <array>
constexpr std::array<int, 3> values = {1, 2, 3};
template <int i> struct A { static constexpr int val = values[i]; };
int main() { A<1> a; }
但是,如果我们使用 values.size()
作为模板参数,我会从 MSVC 编译器收到编译器错误:
int main() { A<values.size()> a; }
错误是表达式未计算为常量。 GCC 编译没有错误。
- 这是 MSVC 编译器的错误吗?
- 是否有 standard/clever 解决方法来规避此错误?
这实际上是 bug/flaw GCC,而不是 MSVC。
A<values.size()> a;
导致您访问 values
超出范围,因为有效索引是 [0, size())
。 MSVC 给你一个错误,它不能这样做,因为它是未定义的行为,并且在常量表达式中不允许这样做。
请注意,clang 也会正确诊断并发出错误:https://godbolt.org/z/vmi86S
MSVC 是对的。在任何 constexpr 上下文中都不能有未定义的行为。否则这不是常量表达式。
行:
int main() { A<values.size()> a; }
基本上是:
constexpr auto i = values[values.size()];
这是越界的。事实上,MSVC 正确诊断错误:
example.cpp <source>(3): error C2131: expression did not evaluate to a constant C:/msvc/v19_16/include\array(187): note: failure was caused by out of range index 3; allowed range is 0 <= index < 3 <source>(4): note: see reference to class template instantiation 'A<3>' being compiled <source>(2): note: see reference to class template instantiation 'std::array<int,3>' being compiled Compiler returned: 2
另一方面,GCC 和 MSVC 都接受此代码:
int main() { A<values.size() - 1> a; }