Reputation: 3109
Is the following a valid C++ code, and why not?
std::array<std::string, 42> a1;
std::array<int, a1.size()> a2;
It doesn't compile in GCC 4.8 (in C++11 mode). There is a simple but inelegant workaround:
std::array<std::string, 42> a1;
std::array<int, sizeof(a1)/sizeof(a1[0])> a2;
So clearly the compiler can figure out the number of elements in std::array. Why std::array::size() is not a constexpr static
function?
EDIT: I have found another workaround:
std::array<std::string, 42> a1;
std::array<int, std::tuple_size<decltype(a1)>::value> a2;
Upvotes: 38
Views: 17346
Reputation: 85531
std::tuple_size
has a specialization for std::array
for this purpose:
std::array<int, 42> a1;
std::array<int, std::tuple_size<decltype(a1)>::value> a2;
Since C++17 can use a shorthand std::tuple_size_v
:
std::array<int, 42> a1;
std::array<int, std::tuple_size_v<decltype(a1)>> a2;
Upvotes: 3
Reputation: 61970
std::array::size
is actually required to be constexpr
per § 23.3.2.1 of the C++11 standard:
23.3.2.4 array::size [array.size]
template <class T, size_t N> constexpr size_type array<T,N>::size() noexcept;
Returns: N
I'm guessing this just slipped past whoever implemented it in GCC.
After testing, this works:
std::array<int, 42> a1;
std::array<int, a1.size()> a2;
This may actually have something to do with std::string
not being a valid constexpr
type to make compile-time instances of, whereas int
is.
Upvotes: 11
Reputation: 283883
You can use the same template-inference method as has always been used for C++98 array bound detection.
template<size_t N, typename T>
constant_integer<N> array_size( const std::array<T, N>& );
Make a nice macro wrapper and enjoy!
Many variations are also possible, such as:
Upvotes: 5
Reputation: 4601
array<T>::size()
is constexpr
, but you can't use it in this way because a1
isn't a constexpr
value. Additionally, it can't be constexpr
because string
isn't a literal type.
However, you can work around this if you want, by deducing the size_t
template parameter. Example:
#include <string>
#include <array>
#include <iostream>
using namespace std;
template<typename>
struct array_size;
template<typename T, size_t N>
struct array_size<array<T,N> > {
static size_t const size = N;
};
array<string, 42> a1;
array<string, array_size<decltype(a1)>::size> a2;
int main() {
cout << a2.size() << endl;
}
Upvotes: 26
Reputation: 18761
It is not static but it is a constexpr
http://www.cplusplus.com/reference/array/array/size/
EDIT: this may not be a bug, take a look at this Error using a constexpr as a template parameter within the same class
Upvotes: 0