#c #stl #standards #c 20 #std-ranges
Вопрос:
#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
}
Смотрите онлайн-демонстрацию
Почему не удается скомпилировать std::views::take(std::uint64_t{})
?
Комментарии:
1. к вашему сведению — работа в 11.2 — live — godbolt.org/z/hnKPn4soz
2. Похоже, это ошибка gcc 11.1.
Ответ №1:
До P2367 регистр по умолчанию views::take(E, F)
был указан как эквивалентный выражению ranges::take_view{E, F}
. Обратите внимание на фигурные скобки.
ranges::take_view<V>
принимает a range_difference_t<V>
(который подписан) в качестве второго аргумента. Инициализация списка отклоняет сужение (например, попытка инициализации a ptrdiff_t
с помощью a uint64_t
), поэтому ваш пример был отклонен.
Однако теперь views::take(E, F)
указано, что выражение эквивалентно ranges::take_view(E, F)
. Со скобками. Что означает отсутствие проверки на сужение, что означает, что прохождение a uint64_t
абсолютно нормально.
libstdc реализовал это изменение 30 апреля, которое, я думаю, было слишком поздно для gcc 11.1, но это изменение есть в gcc 11.2, который принимает ваш код.
Ответ №2:
range | std::views::take(n)
является выражением, эквивалентным std::ranges::take_view(range, n)
, которое принимает a ranges::range_difference_t<V>
.
Следуя псевдонимам, gcc 11.1 не хочет unsigned long
считать пригодным для использования там, где long
требуется a