Is there a reason for zero sized std::array in C++11?
Consider the following piece of code, which is perfectly acceptable by a C++11 compiler:
#include <array>
#include <iostream>
auto main() -> int {
std::array<double, 0> A;
for(auto i : A) std::cout << i << std::endl;
return 0;
}
According to the standard § 23.3.2.8 [Zero sized arrays]:
1
Array shall provide support for the special caseN == 0
.
2
In the case thatN == 0
,begin() == end() ==
unique value. The return value ofdata()
is unspecified.
3
The effect of callingfront()
orback()
for a zero-sized array is undefined.
4
Member functionswap()
shall have a noexcept-specification which is equivalent tonoexcept(true)
.
As displayed above, zero sized std::array
s are perfectly allowable in C++11, in contrast with zero sized arrays (e.g., int A[0];
) where they are explicitly forbidden, yet they are allowed by some compilers (e.g., GCC) in the cost of undefined behaviour.
Considering this "contradiction", I have the following questions:
Why the C++ committee decided to allow zero sized
std::array
s?Are there any valuable uses?
Solution 1:
If you have a generic function it is bad if that function randomly breaks for special parameters. For example, lets say you could have a template function that takes N
random elements form a vector:
template<typename T, size_t N>
std::array<T, N> choose(const std::vector<T> &v) {
...
}
Nothing is gained if this causes undefined behavior or compiler errors if N
for some reason turns out to be zero.
For raw arrays a reason behind the restriction is that you don't want types with sizeof T == 0
, this leads to strange effects in combination with pointer arithmetic. An array with zero elements would have size zero, if you don't add any special rules for it.
But std::array<>
is a class, and classes always have size > 0. So you don't run into those problems with std::array<>
, and a consistent interface without an arbitrary restriction of the template parameter is preferable.
Solution 2:
One use that I can think of is the return of zero length arrays is possible and has functionality to be checked specifically.
For example see the documentation on the std::array
function empty()
. It has the following return value:
true if the array size is 0, false otherwise.
http://www.cplusplus.com/reference/array/array/empty/
I think the ability to return and check for 0 length arrays is in line with the standard for other implementations of stl types, for eg. Vectors and maps and is therefore useful.
Solution 3:
As with other container classes, it is useful to be able to have an object that represents an array of things, and to have it possible for that array to be or become empty. If that were not possible, then one would need to create another object, or a managing class, to represent that state in a legal way. Having that ability already contained in all container classes, is very helpful. In using it, one then just needs to be in the habit of relating to the array as a container that might be empty, and checking the size or index before referring to a member of it in cases where it might not point to anything.