Here it is written that std::ranges::size
should return an unsigned integer. However, when I use it on an Eigen vector (with Eigen 3.4) the following compiles:
Eigen::VectorXd x;
static_assert(std::same_as<Eigen::VectorXd::Index,
decltype(std::ranges::size(x))>);
where Eigen::VectorXd::Index
is notoriously a signed integer. By looking at the implementation of std::ranges::size
, I noticed that the return type is inferred from the return type of x.size()
, which is precisely Eigen::VectorXd::Index
. Is this a bug of std::ranges::size
? Or is this expected?
Update 27/12/2021
The C++ reference page linked above has eventually changed the description of the std::ranges::size
function: it only returns an integer, not necessarily an unsigned one!
Is this a bug of std::ranges::size?
No. The cppreference documentation is misleading. There is no requirement for std::ranges::size
to return an unsigned integer. In this case, it returns exactly what Eigen::VectorXd::size
returns.
For ranges that model ranges::sized_range
, that would be an unsigned integer, but Eigen::VectorXd
evidently does not model such range.
But then what is the purpose of std::ranges::ssize compared to std::ranges::size?
The purpose of std::ranges::ssize
is to be a generic way to get a signed value regardless of whether std::ranges::size
returns signed or unsigned. There is no difference between them in cases where std::ranges::size
returns a signed type.
Is there a reference to back up what you state?
Yes. See the C++ standard:
[range.prim.size]
Otherwise, if
disable_sized_range<remove_cv_t<T>>
([range.sized]) isfalse
andauto(t.size())
is a valid expression of integer-like type ([iterator.concept.winc]),ranges::size(E)
is expression-equivalent toauto(t.size())
.