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?
CodePudding user response:
It's very much intended that the sized_range
concept and the corresponding ranges::size
customization point take no position on the signed/unsigned holy wars. ranges::size
does convert to unsigned when computing from the distance between begin and end, for consistency with the existing standard library, but user types are not required to agree with that choice.
CodePudding user response:
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())
.