为啥 std::array::size constexpr 具有简单类型(int,double,...)而不是 std::vector (GCC)?

Posted

技术标签:

【中文标题】为啥 std::array::size constexpr 具有简单类型(int,double,...)而不是 std::vector (GCC)?【英文标题】:Why is std::array::size constexpr with simple types (int, double, ...) but not std::vector (GCC)?为什么 std::array::size constexpr 具有简单类型(int,double,...)而不是 std::vector (GCC)? 【发布时间】:2016-04-14 12:37:07 【问题描述】:

以下代码:

std::array<int, 4> arr1;
std::array<float, arr1.size()> arr2;

...与gccclang 一起编译,因为std::array::size 被认为是constexpr

但以下内容无法与gcc(版本 5.3.0 20151204)一起编译:

std::array<std::vector<int>, 4> arr1;
std::array<std::vector<double>, arr1.size()> arr2;

对我来说,如果第一个代码有效,那么没有理由编译失败,但由于我没有找到很多关于此的帖子,我不知道它是 gcc 错误还是 @987654330 @扩展?

来自gcc 的错误(我不太明白...):

main.cpp: In function 'int main()':
main.cpp:6:46: error: call to non-constexpr function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]'
     std::array<std::vector<double>, arr1.size()> arr2;
                                              ^
In file included from main.cpp:1:0:
/usr/local/include/c++/5.3.0/array:170:7: note: 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]' is not usable as a constexpr function because:
       size() const noexcept  return _Nm; 
       ^
/usr/local/include/c++/5.3.0/array:170:7: error: enclosing class of constexpr non-static member function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]' is not a literal type
/usr/local/include/c++/5.3.0/array:89:12: note: 'std::array<std::vector<int>, 4ul>' is not literal because:
     struct array
            ^
/usr/local/include/c++/5.3.0/array:89:12: note:   'std::array<std::vector<int>, 4ul>' has a non-trivial destructor
main.cpp:6:46: error: call to non-constexpr function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]'
     std::array<std::vector<double>, arr1.size()> arr2;
                                              ^
main.cpp:6:48: note: in template argument for type 'long unsigned int' 
     std::array<std::vector<double>, arr1.size()> arr2;
                                                ^

【问题讨论】:

有趣的是 MSVS2015 和 clang 都可以编译。 MSVS intellisense 不喜欢它但被编译器接受。 如果您需要解决方法,可以使用 tuple_size&lt;array&lt;T,N&gt;&gt;::value:/ 【参考方案1】:

我认为这与CWG issue 1684 有关。以前,constexpr 要求包括:

constexpr 函数所属的类应为文字类型

std::array&lt;std::vector&lt;int&gt;, 4&gt; 不是文字类型,因此它的size() 成员函数不会是constexpr。然而,新的措辞允许非文字类型的constexpr 非静态成员函数,假设这些函数满足constexpr 的所有其他要求(array&lt;T,N&gt;::size() 显然满足)。

根据新的措辞,这是一个 gcc 错误。之前提交为66297。

【讨论】:

以上是关于为啥 std::array::size constexpr 具有简单类型(int,double,...)而不是 std::vector (GCC)?的主要内容,如果未能解决你的问题,请参考以下文章

为啥要设计一个库来在 Javascript 中使用 const [] 而不是 const ?

为啥非 const 方法是私有的时不调用公共 const 方法?

为啥我们不能在 TypeScript 类中定义一个 const 字段,为啥静态只读不起作用?

为啥 const 方法不能返回非常量引用?

为啥箭头函数名称必须是 const/let?

为啥 const int main = 195 会导致程序正常工作,但没有 const 会导致分段错误?