Reputation: 42225
#include <cstdint>
#include <ranges>
int main()
{
auto const il = {1, 2, 3, 4, 5, 6};
auto const n1 = std::int32_t{3};
auto const n2 = std::uint32_t{3};
auto const n3 = std::int64_t{3};
auto const n4 = std::uint64_t{3};
il | std::views::take(n1); // ok
il | std::views::take(n2); // ok
il | std::views::take(n3); // ok
il | std::views::take(n4); // error
}
See online demo
Why can't compile std::views::take(std::uint64_t{})
?
Upvotes: 1
Views: 123
Reputation: 302738
Prior to P2367, the default case of views::take(E, F)
was specified to be expression-equivalent to ranges::take_view{E, F}
. Note the braces.
ranges::take_view<V>
takes a range_difference_t<V>
(which is signed) as its second argument. List-initialization rejects narrowing (e.g. attempting to initialize a ptrdiff_t
with a uint64_t
), so your example was rejected.
However, now views::take(E, F)
is specified to be expression-equivalent to ranges::take_view(E, F)
. With parentheses. Which means no check for narrowing, which means passing a uint64_t
is totally fine.
libstdc++ implemented that change on Apr 30 which I guess was too late for gcc 11.1 but that change is there in gcc 11.2, which accepts your code.
Upvotes: 3
Reputation: 62576
range | std::views::take(n)
is expression equivalent to std::ranges::take_view(range, n)
, which takes a ranges::range_difference_t<V>
.
Following the aliases through, gcc 11.1 doesn't want to consider unsigned long
as usable where a long
is wanted
Upvotes: 1