Example 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
Gives 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 while the second one does not compile?
std::array is a container that encapsulates fixed size arrays. This container is an aggregate type with the same semantics as a struct holding a C-style array T[N] as its only non-static data member. Unlike a C-style array, it doesn't decay to T* automatically.
std::array contains a built-in array, which can be initialized via an initializer list, which is what the inner set is. The outer set is for aggregate initialization.
Like arrays, we initialize an std::array by simply assigning it values at the time of declaration. For example, we will initialize an integer type std::array named 'n' of length 5 as shown below; std::array<int, 5> n = {1, 2, 3, 4, 5}; There is another way of initializing an std::array which is shown below.
You should not notice any difference in runtime performance while you still get to enjoy the extra features. Using std::array instead of int[] style arrays is a good idea if you have C++11 or boost at hand.
The type std::string is not a literal type meaning that it cannot be manipulated as part of a constexpr function at compile time. At compile time, the compiler attempts to evaluate the array_string's size() function. The functions first type parameter as 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 refer you to the following to learn more about constexpr.
http://en.cppreference.com/w/cpp/language/constexpr
I would refer you to the following 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 literal types and std::string is not. You can try it out with other types to see what are or aren't literal types.
#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 that helps.
John
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With