gpt4 book ai didi

c++ - 为什么 views::reverse 不适用于 iota_view

转载 作者:行者123 更新时间:2023-12-04 12:19:16 25 4
gpt4 key购买 nike

我有 following C++ program ,由于某种原因我不能使用 int64_t作为模板参数。

#include <iostream>
#include <ranges>

template<typename T>
void fn() {
for (auto val : std::ranges::iota_view{T{1701}, T{8473}}
| std::views::reverse
| std::views::take(5))
{
std::cout << val << std::endl;
}

}

int main()
{
fn<int16_t>();
fn<int32_t>();
// does not compile:
// fn<int64_t>();
}
这是预期的(我做错了什么),还是只是编译器/标准库中的一些不幸的错误?
注意:当我删除 std::views::reverse 时代码编译为 int64_t还。

最佳答案

这是一个 libstdc++ 错误,已提交 100639 .
iota是一个令人惊讶的复杂范围。特别是,我们需要选择一个 difference_type对于我们正在递增以避免溢出的类型,它足够宽(另请参见 P1522 )。结果,我们在 [range.iota] :

Let IOTA-DIFF-T(W) be defined as follows:

  • [...]
  • Otherwise, IOTA-DIFF-T(W) is a signed integer type of width greater than the width of W if such a type exists.
  • Otherwise, IOTA-DIFF-T(W) is an unspecified signed-integer-like type ([iterator.concept.winc]) of width not less than the width of W.

[Note 1: It is unspecified whether this type satisfies weakly_­incrementable. — end note]


对于 iota_view<int64_t, int64_t> , 我们的差异类型是 __int128 (足够宽的带符号整数类型)。在 gcc 上, signed_integral<__int128>false在符合模式( -std=c++20 )和 true 下编译时带有扩展名 ( -std=gnu++20 )。
现在,在 libstdc++ 中, reverse_viewimplemented as :
template<typename _Iterator>
class reverse_iterator
: public iterator<typename iterator_traits<_Iterator>::iterator_category,
typename iterator_traits<_Iterator>::value_type,
typename iterator_traits<_Iterator>::difference_type,
typename iterator_traits<_Iterator>::pointer,
typename iterator_traits<_Iterator>::reference>
{
// ...
typedef typename __traits_type::reference reference;
// ...
_GLIBCXX17_CONSTEXPR reference operator*() const;
// ...
};
不是这样 reverse_iterator被指定。 [reverse.iterator]定义 reference键入:
using reference = iter_reference_t<Iterator>;
不同的是后者只是表示 *it的类型,而前者实际上是通过 iterator_traits并试图确定是什么 reference表示如果 It::reference不作为类型存在。该决定在 [iterator.traits] 中指定:

Otherwise, if I satisfies the exposition-only concept cpp17-input-iterator, iterator_­traits<I> has the following publicly accessible members: [...]


哪里 referenceI::reference如果存在或 iter_reference_t<I>如果没有。看起来是一回事,但是我们要先满足 cpp17-input-iterator<I> .和 cpp17-input-iterator<I>除其他外,要求:
template<class I>
concept cpp17-input-iterator =
cpp17-iterator<I> && equality_­comparable<I> && requires(I i) {
// ...
requires signed_­integral<typename incrementable_traits<I>::difference_type>;
};
所以基本上, iterator_t<iota_view<int64_t, int64_t>>满足 cpp17-input-iterator当且仅当 signed_integral<__int128>成立,这仅在我们在 -std=gnu++20 中编译时才成立。 .
但是我们不需要满足这个要求,因为 reverse_iterator<I>应该直接使用 iter_reference_t<I>并且不通过 iterator_traits ,哪些方面必须检查 signed_integral<__int128> .

关于c++ - 为什么 views::reverse 不适用于 iota_view<int64_t, int64_t>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67573305/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com