Error creating instance of std :: array using std :: array :: size

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

Compiling with g ++ 4.8.4 (Ubuntu 14.04)

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

Throws the following error message

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

Can someone explain this error? Why does the first example work and the second does not compile?

+5
source share
1 answer

The std :: string type is not a literal type, meaning that it cannot be manipulated as part of the constexpr function at compile time. At compile time, the compiler tries to evaluate the array_string size () function. The parameter of the first type of functions, which you can see in the first error, is set to std :: basic_string <char> (aka std :: string); therefore, since std :: string is not a literal type, the function cannot be evaluated as a constexpr function at compile time, and you have an error.

I would like to direct you to the next to learn more about constexpr.

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

I would like to direct you to the next to learn about literal types.

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

Finally, try the following simple code and you will see that int and float are literals, while std :: string is not. You can try it with other types to see which types are or are not literal.

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

Hope this helps.

John

+2
source

Source: https://habr.com/ru/post/1242852/


All Articles