为什么视图::反向不适用于iota_view<int64_t,int64_t>
Why does views::reverse not work with iota_view<int64_t, int64_t>
我有以下C++程序,由于某种原因我不能使用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] 中有:
让我们
IOTA-DIFF-T(W)
定义如下:
- [...]
- 否则,
IOTA-DIFF-T(W)
是宽度大于W
宽度的有符号整数类型(如果存在此类类型)。- 否则,
IOTA-DIFF-T(W)
是一个未指定的有符号整数类类型([iterator.concept.winc]),其宽度不小于W
的宽度。[注1:未指定此类型是否满足
weakly_incrementable
— 尾注]
对于iota_view<int64_t, int64_t>
,我们的差分类型是__int128
(一个足够宽的有符号积分类型)。在 gcc 上,signed_integral<__int128>
在以符合模式 (-std=c++20
) 编译并使用扩展 (-std=gnu++20
true
时false
。
现在,在libstdc++中,reverse_view
实现为:
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] 中指定:
否则,如果
I
满足仅博览会概念cpp17-input-iterator
,iterator_traits<I>
具有以下可公开访问的成员:[...]
如果reference
存在,则I::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>
的步骤。
- 从不同线程使用int64的不同字节安全吗
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- 你能把一个向量<int64>投射到一个向量<uint8>吗
- 如何显式调用运算符<<
- Int64 和 time_t 之间的 C++ 重载歧义
- 模板操作员&lt;未打电话
- C / CUDA中的模板方法是3个角括号(&lt;&lt;&lt;)
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 错误:调用"std::vector<:vector<int>>::p ush_back(std::vector<std::__cxx11::basic_string<
- 在 c++ 中设置 int64 值的最高四位
- C 建造者Clang STD :: Sill,找不到超载的操作员&lt;
- 为什么STD :: MAP需要操作员&lt;以及我如何写一个
- 为什么“操作员”需要const但不是为“运营商&lt;”
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla