Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is std::ranges::size supposed to return an unsigned integer?

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!

like image 737
fdev Avatar asked Dec 22 '21 18:12

fdev


People also ask

What is the range of unsigned int?

An unsigned integer is a 32-bit datum that encodes a nonnegative integer in the range [0 to 4294967295].

Can unsigned int overflow?

"A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type."

Is it suggested to compare signed and unsigned numbers in C++?

Sure, comparisons between signed and unsigned would be slower, but their result would be more correct in some sense. @Nawaz Your bottom line conclusion is incorrect, unfortunately: if the signed type can contain the unsigned type, the unsigned will be converted to the signed type and not the opposite.


Video Answer


2 Answers

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.

like image 194
T.C. Avatar answered Nov 14 '22 22:11

T.C.


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]) is false and auto(t.size()) is a valid expression of integer-like type ([iterator.concept.winc]), ranges​::​size(E) is expression-equivalent to auto(​t.size()).

like image 25
eerorika Avatar answered Nov 14 '22 22:11

eerorika