What does the C++ standard say about what sizeof(std::array<char, N>) should be (for some constant N)?
In a comment to a different question, it was mentioned that std::array is not always "stack allocated". The comment was in response to a different comment that speculated that putting a too large of a constant for std::array that is declared as a local variable could cause the program to abort due to insufficient resources for the "stack allocated" variable. I assume the followup comment meant that it would be possible for std::array to somehow switch to a dynamic allocation mode.
I could imagine that there could be some kind of SFINAE could be applied for an array size threshold that triggers a specialization of std::array that actually dynamically allocates an array and manages it. In that case, the sizeof(std::array<...>) might just be the size of a pointer. Is that allowed to happen?
Obviously sizeof(std::array<char, N>) != N if N == 0. It also doesn't necessarily hold for N > 0.
§23.3.2.1 [array.overview]/p1-2:
The header
<array>defines a class template for storing fixed-size sequences of objects. An array supports random access iterators. An instance ofarray<T, N>storesNelements of typeT, so thatsize() == Nis an invariant. The elements of an array are stored contiguously, meaning that ifais anarray<T, N>then it obeys the identity&a[n] == &a[0] + nfor all0 <= n < N.An array is an aggregate (8.5.1) that can be initialized with the syntax
array<T, N> a = { initializer-list };where
initializer-listis a comma-separated list of up toNelements whose types are convertible toT.
§8.5.1 [dcl.init.aggr]/p1:
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
Since array is an aggregate type, it can't have a custom constructor that performs dynamic allocation, and it must store the elements directly since it must be able to be initialized from a initializer list using aggregate initialization. However, nothing in the standard prevents the implementation from adding extra stuff after its C-style array member, as long as array<T, N> a = { initializer-list }; has the defined semantics when the initializer-list contains at most N members. An implementation that looks like
template<typename T, size_t N>
struct array {
//typedefs and member functions omitted
T _Elems[N];
double _Because_I_can;
};
// specialization for N == 0 case omitted
is perfectly legal. Therefore, there's no guarantee that sizeof(std::array<char, N>) == N.
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