Constexpr和模板:编译错误?

问题描述 投票:0回答:2

如预期了以下工作:

#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; }

但是,我从MSVC编译器编译器错误,如果我们使用values.size()作为模板参数:

int main() { A<values.size()> a; }

该错误是表达式的结果不是一个常数。在GCC编译没有错误。

  • 这是MSVC编译器的一个bug?
  • 是否有一个标准的/聪明的解决办法绕过这个错误?
c++ templates constexpr
2个回答
8
投票

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; }

3
投票

这实际上是海湾合作委员会的错误/缺陷,而不是MSVC。

A<values.size()> a;

使你访问values超出了范围,因为有效的指标是[0, size())。 MSVC给你一个错误,它不能这样做,因为它是不确定的行为,而不是在一个常量表达式允许的。

需要注意的是铛也正确地诊断这并发出错误:https://godbolt.org/z/vmi86S

© www.soinside.com 2019 - 2024. All rights reserved.