使用std::array::size实例化std::array时出现错误

6

示例代码 test.cpp

#include <array>
#include <string>

int main ()
{
  // OK
  const std::array<int, 2> array_int = {42, 1337};

  std::array<float, array_int.size()> array_float_ok;

  // Error
  const std::array<std::string, 2> array_string = {"foo", "bar"};

  std::array<float, array_string.size()> array_float_error;

  return 0;
}

使用g++ 4.8.4(Ubuntu 14.04)进行编译

g++ -Wall -std=c++0x test.cpp -o test

给出以下错误信息
test.cpp: In function ‘int main()’:
test.cpp:14:39: error: call to non-constexpr function ‘constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::basic_string<char>; long unsigned int _Nm = 2ul; std::array<_Tp, _Nm>::size_type = long unsigned int]’
   std::array<float, array_string.size()> array_float_error;
                                       ^
In file included from test.cpp:1:0:
/usr/include/c++/4.8/array:162:7: note: ‘constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::basic_string<char>; long unsigned int _Nm = 2ul; std::array<_Tp, _Nm>::size_type = long unsigned int]’ is not usable as a constexpr function because:
       size() const noexcept { return _Nm; }
       ^
/usr/include/c++/4.8/array:162: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::basic_string<char>; long unsigned int _Nm = 2ul; std::array<_Tp, _Nm>::size_type = long unsigned int]’ is not a literal type
/usr/include/c++/4.8/array:81:12: note: ‘std::array<std::basic_string<char>, 2ul>’ is not literal because:
     struct array
            ^
/usr/include/c++/4.8/array:81:12: note:   ‘std::array<std::basic_string<char>, 2ul>’ has a non-trivial destructor
test.cpp:14:39: error: call to non-constexpr function ‘constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::basic_string<char>; long unsigned int _Nm = 2ul; std::array<_Tp, _Nm>::size_type = long unsigned int]’
   std::array<float, array_string.size()> array_float_error;
                                       ^
test.cpp:14:40: note: in template argument for type ‘long unsigned int’
   std::array<float, array_string.size()> array_float_error;
                                        ^
test.cpp:14:59: error: invalid type in declaration before ‘;’ token
   std::array<float, array_string.size()> array_float_error;
                                                           ^
test.cpp:9:39: warning: unused variable ‘array_float_ok’ [-Wunused-variable]
   std::array<float, array_int.size()> array_float_ok;
                                       ^
test.cpp:14:42: warning: unused variable ‘array_float_error’ [-Wunused-variable]
   std::array<float, array_string.size()> array_float_error;
                                          ^

有人能解释一下这个错误吗?为什么第一个例子可以工作而第二个例子无法编译?


明显的重复 - 最近看到过几次这个问题。 - Lightness Races in Orbit
可能是constexpr和奇怪的错误的重复。 - mindriot
3
可能是在编译时获取std::array元素数量的方法的重复问题。 - sergej
我并不完全理解链接问题中给出的答案。它提到了“a1不是一个constexpr值”(因为std::string不能是constexpr),在我的情况下对应于array_string。这是否意味着array_int是一个隐式的constexpr值(因为我没有将其指定为constexpr)? - simon
@simon 这看起来像是gcc编译器错误;我使用g++ 5.1.1测试了它,得到了相同的结果;而clang++ 3.5.0则可以正确编译这段代码。无论存储在std::array中的类型是什么,size()方法都应该是constexpr的。 - Patryk Obara
1个回答

2

类型std::string不是字面量类型,这意味着它不能作为constexpr函数的一部分在编译时进行操作。在编译时,编译器尝试评估array_string的size()函数。正如您在第一个错误中看到的,该函数的第一个类型参数设置为std::basic_string < char >(也称为std::string);因此,由于std::string不是字面量类型,该函数无法作为constexpr函数在编译时进行评估,从而导致错误。

我建议您参考以下内容了解更多关于constexpr的知识。

http://en.cppreference.com/w/cpp/language/constexpr

我建议你参考以下内容了解字面类型。

http://en.cppreference.com/w/cpp/concept/LiteralType

最后,尝试以下简单的代码,你会发现int和float是字面类型,而std::string不是。你可以尝试其他类型来查看哪些是字面类型,哪些不是。
#include <iostream>
int main(int argc, char** argv) 
{ 
    std::cout << std::is_literal_type<int>::value << std::endl;
    std::cout << std::is_literal_type<float>::value << std::endl;
    std::cout << std::is_literal_type<std::string>::value << std::endl;
    return 0;
}                                  

希望有所帮助。
约翰

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接