I'm trying to imagine a scenario where std::size
is inappropriate for std::tuple
and I'm coming up blank. It supports std::array
, but that has its own size()
method, so there's no need to specialize. But it also supports T[N]
, presumably because it's statically sized even if it doesn't have a size()
method (it doesn't even have std::tuple_size_v
.)
So why doesn't std::tuple
get std::size
support or a size()
method? I even thought maybe having std::tuple_size_v
means it doesn't need one, but the same goes for std::array
.
CodePudding user response:
First, some background to understand what the purpose of std::size
even is:
Similar to how iterators are generalisations of what pointers are, the standard containers are generalisations of what arrays are (pointers being iterators of arrays). They all contain elements of homogeneous types i.e. all elements have the same type, and they can be iterated over.
Unlike pointers which do actually satisfy the abstract iterator concept, arrays were not given the same honour. This may have been because the interface of pointer/iterator could be satisfied by a few simple operators, while containers required several functions to use. Perhaps the committee preferred the object oriented interface of member functions over free functions that are the only possibility for arrays.
It can nevertheless be useful to write generic functions and classes that can treat arrays through the same interface. Although an array wrapper template was introduced in C 11 (std::array
), which actually is a container (well, almost; it doesn't satisfy a few properties that containers are required to have), it cannot satisfy all use cases where refactoring is not an option (consider for example C interfaces).
C 11 and later versions also introduced free functions (templates) that do nothing but forward the call to the corresponding member function of a container, overloaded with a template that does the identical operation on an array. These overloads are such generic interface that can be used with arrays and containers within templates. They are:
std::swap C 11
std::{c,}begin C 11
std::{c,}end C 11
std::size C 17
std::empty C 17
std::data C 17
Besides being generic, std::end
and std::size
in particular also implement functionality that is error prone to beginners.
Now for the question:
why isn't size/ssize defined for tuple (or wherever tuple_size_v is)?
The original proposal is n4017. It contains no rationale for not supporting tuples. I don't know if the committee ever even thought to consider it. But if they did, since such feature isn't in the standard, then they would have rejected (tenatively at minimum) the idea.
Tuple isn't a container, and it doesn't have the member function size
. It's significantly further from a container than an array is. Crucially, the elements of a tuple are heterogeneous; they consist of objects of differing types. They cannot be iterated over with iterators in the same sense that containers can be.
Tuples could however be seen as an even higher generalisation of containers. Perhaps in distant future, Boost.Fusion will be incorporated into the standard and we will have a common interface with containers and tuples. But if we are in that timeline, then we are still in the relative past. It won't happen until/unless it has been proposed and accepted into the standard.
Curiously, std::tuple_size
is a common interface between std::tuple
and std::array
(but not bare array).