【问题标题】:Error when instantiating std::array using std::array::size使用 std::array::size 实例化 std::array 时出错
【发布时间】:2016-05-23 11:34:49
【问题描述】:

示例代码 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;
                                          ^

有人可以解释这个错误吗?为什么第一个示例可以运行,而第二个示例无法编译?

【问题讨论】:

  • 绝对是个骗子——最近看到这个问题好几次了
  • 我不完全理解链接问题中给出的答案。它提到“a1 不是 constexpr 值”(因为 std::string 不能是 constexpr)在我的情况下对应于 array_string。这是否意味着 array_int 是隐式的 constexpr 值(因为我没有将其指定为 constexpr)?
  • @simon 这看起来像是 gcc 中的编译器错误;我使用 g++ 5.1.1 对其进行了测试,结果相同; clang++ 3.5.0 正确编译了这段代码。 size() 方法应该是 constexpr,无论存储在 std::array 中的类型如何。

标签: c++ arrays c++11 std constexpr


【解决方案1】:

类型 std::string 不是文字类型,这意味着它不能在编译时作为 constexpr 函数的一部分进行操作。在编译时,编译器尝试评估 array_string 的 size() 函数。您可以在第一个错误中看到的函数第一个类型参数设置为 std::basic_string (aka 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;
}                                  

希望对您有所帮助。

约翰

【讨论】:

    猜你喜欢
    • 2012-12-08
    • 2018-06-29
    • 2021-03-19
    • 2020-03-22
    • 1970-01-01
    • 2021-11-16
    • 2021-09-28
    • 2017-04-17
    • 1970-01-01
    相关资源
    最近更新 更多