为什么无法编译 std::views::take(std::uint64_t{})?

Why can't compile std::views::take(std::uint64_t{})?

#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
}

online demo

为什么编译不了std::views::take(std::uint64_t{})?

range | std::views::take(n) 是等价于 std::ranges::take_view(range, n) 的表达式,需要 a ranges::range_difference_t<V>.

通过别名,gcc 11.1 不想在需要 long 的地方考虑 unsigned long 可用

P2367 之前,views::take(E, F) 的默认大小写被指定为等价于 ranges::take_view{E, F} 的表达式。注意大括号。

ranges::take_view<V>range_difference_t<V>(已签名)作为其第二个参数。列表初始化拒绝缩小(例如,尝试用 uint64_t 初始化 ptrdiff_t),因此您的示例被拒绝。

但是,现在 views::take(E, F) 被指定为等同于 ranges::take_view(E, F) 的表达式。带括号。这意味着不检查缩小,这意味着传递 uint64_t 完全没问题。

libstdc++ 在 Apr 30 上实现了该更改,我想这对于 gcc 11.1 来说为时已晚,但该更改存在于接受您的代码的 gcc 11.2 中。