我想为客户数据结构提供一个视图,它有自己的迭代器。我编写了一个小程序来测试它,如下所示。如果我取消对begin()的注释,它就会工作。但是如果我使用DummyIter,那么我会得到一个编译错误。
在我的完整程序中,我实现了一个完整的迭代器,但为了简单起见,我把它缩小到了必要的函数。
#include <iostream>
#include <ranges>
#include <vector>
template<class T>
struct DummyIter
{
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
DummyIter() = default;
auto operator*() const { T t; return t; }
auto& operator++() { return *this; }
auto operator++(int val) { DummyIter tmp = *this; ++*this; return tmp; }
auto operator==(const DummyIter& iter) const { return true; }
};
template<class V>
struct DummyView : std::ranges::view_interface<DummyView<V>>
{
//auto begin() const { return std::ranges::begin(v); }
auto begin() const { return DummyIter<int>(); }
auto end() const { return std::ranges::end(v); }
V v;
};
int main() {
auto view = DummyView<std::vector<int>>();
view | std::views::filter([](auto i) { return i > 0; });
}
我使用的是GCC 11.1.0。我在迭代器中缺少了什么使其符合范围?
error: no match for 'operator|' (operand types are 'DummyView<std::vector<int> >' and 'std::ranges::views::__adaptor::_Partial<std::ranges::views::_Filter, main()::<lambda(auto:15)> >')
37 | view | std::views::filter([](auto i) { return i > 0; });
| ~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | std::ranges::views::__adaptor::_Partial<std::ranges::views::_Filter, main()::<lambda(auto:15)> >
| DummyView<std::vector<int> >
检查此类范围的方法是:
input_iterator
。sentinel_for
您的迭代器。这些检查将告诉您缺少哪些功能。
在这种情况下,即:
using I = DummyIter<int>;
using S = std::vector<int>::const_iterator;
static_assert(std::input_iterator<I>); // ok
static_assert(std::sentinel_for<S, I>); // error
问题是S
不是sentinel_for
因此,您需要添加另一个
运算符==
到DummyIter
这不起作用,因为开始
和结束
的返回类型不匹配。所以基本上这些迭代器不能相互比较。
证明:
最低要求是开始()
和结束()
的结果是可比的。当不知道范围的大小时,开始()
和结束()
的不同类型是有用的。这里有一个关于哨兵的很好的解释(在注释中提到)。
因为您的DummyView
不符合range
的概念,准确地说,就是视图的返回类型。end()
不能用作视图的哨兵。begin()
,因为没有合适的运算符==()
来与std::vector进行比较
解决方法只是添加
bool运算符==(std::向量
template<class T>
struct DummyIter {
// ...
bool operator==(std::vector<T>::const_iterator) const;
};
演示
我可以看到返回。但是现在已经添加到C++20标准中,为什么返回?cppreference指定: 返回值 等于last的迭代器。 这个选择背后的理性是什么? 与相比,用例的优势是什么?
我无法让我的用户定义的容器使用std::ranges。如果迭代器只是一个< code>int*的话,我的容器可以工作,但是一旦我创建了自己的迭代器类,就会出现编译器错误。 这是有效的。 https://godbolt.org/z/nxr1qe 使用我自己的迭代器,它不起作用。 https://godbolt.org/z/o9rzhf 为了实现这一点,是否需要为<code>std::ranges</
我知道这个问题在这个论坛上已经被问过好几次了。但我仍在发帖,因为没有一个答案看起来是具体的。专家们,你们能帮我理解什么时候使用迭代器吗。当我们有一个非常大的数据集时,我们是理想地使用它,还是当我们有大量数据要返回时,将其用作方法的返回类型?
我想在JSF应用程序中配置自定义范围。我们在WebSphere8.0/8.5上使用JSF2.0和Primefaces 5.3.17。目前,我们有RequestScope核心和SessionScope模型bean以及命名注释。模型通过注入传递到核心。现在,我们需要提供一种在许多浏览器选项卡上与模型并行工作的方法。我们的想法是使用过滤器将生成的选项卡id注入到响应中,然后,稍后从post请求中提取它,
我试图编写一些代码来执行函数式序列的创建。我写了一个函数range它返回一个对象,你可以迭代它,foreach样式,以遍历数字a,a 1,...,b - 1。然后我写了另一个函数map它返回另一个可迭代对象,其中序列中的每个元素都是使用可迭代对象的相应元素调用的结果。 如果我使用< code>-O1或更低版本进行编译,这将按预期工作;使用< code>-O2或更高版本,我的foreach循环(在底
考虑一个大型内存容器。在这个简单的例子中 span允许我在内存上创建一个轻量级视图。现在,我只想打印跨度: 输出: 现在我想制作子集(这是实际上作为视图变得有用的地方)。我可以使用迭代器来指定我的范围并从调用这个构造函数(3) 但这行不通: C没有与参数列表匹配的构造函数实例参数类型为:(std::\u Vector\u iterator 有可能使用接受指针和大小的构造函数(2): 但这违背了迭代