gpt4 book ai didi

c++ - 在 C++20 中,如何编写连续迭代器?

转载 作者:行者123 更新时间:2023-12-03 10:05:30 25 4
gpt4 key购买 nike

C++20 对 std::contiguous_iterator_tag 有明确的库支持.一些 STL 算法(例如 std::copy )可以在连续迭代器上表现得更好。但是,我不清楚程序员应该如何访问这个新功能。
为了论证起见,让我们假设我们有一个完全符合 C++20 的库实现。我想编写最简单的连续迭代器。
Here's my first attempt.

#include <iterator>

class MyIterator {
int *p_;
public:
using value_type = int;
using reference = int&;
using pointer = int*;
using difference_type = int;
using iterator_category = std::contiguous_iterator_tag;
int *operator->() const;
int& operator*() const;
int& operator[](int) const;
MyIterator& operator++();
MyIterator operator++(int);
MyIterator& operator--();
MyIterator operator--(int);
MyIterator& operator+=(int);
MyIterator& operator-=(int);
friend auto operator<=>(MyIterator, MyIterator) = default;
friend int operator-(MyIterator, MyIterator);
friend MyIterator operator+(MyIterator, int);
friend MyIterator operator-(MyIterator, int);
friend MyIterator operator+(int, MyIterator);
};

namespace std {
int *to_address(MyIterator it) {
return it.operator->();
}
}

static_assert(std::contiguous_iterator<MyIterator>); // FAILS
这在 GCC/libstdc++ 和 MSVC/STL 上都失败了;但它应该吗?
对于我的下一次尝试,我专门 pointer_traits<MyIterator> . MyIterator实际上不是指针,所以我没有在 pointer_traits 中放入任何东西除了图书馆需要的一个功能。 This is my second attempt :
#include <iterator>

class MyIterator {
~~~
};

template<>
struct std::pointer_traits<MyIterator> {
int *to_address(MyIterator it) {
return it.operator->();
}
};

static_assert(std::contiguous_iterator<MyIterator>); // OK!
这是我应该做的吗?感觉非常hacky。 (需要明确的是:我的第一次失败尝试也感觉非常糟糕。)
我错过了一些更简单的方法吗?
特别是, MyIterator有什么办法吗?本身来保证它是连续的,只使用成员和 friend 以及可以在类的主体中定义的东西?就像,如果 MyIterator定义在某个深度嵌套的命名空间中,我不想为了打开 namespace std 而一路突破到顶级命名空间.

编辑添加:Glen Fernandes 告诉我有一个更简单的方法——我应该添加一个 element_type类型定义, like this! (而且我可以在 C++20 中删除 iterator_traits ' 大 5 个 typedef 中的 3 个。)这看起来更好!
#include <iterator>

class MyIterator {
int *p_;
public:
using value_type = int;
using element_type = int;
using iterator_category = std::contiguous_iterator_tag;
int *operator->() const;
int& operator*() const;
int& operator[](int) const;
MyIterator& operator++();
MyIterator operator++(int);
MyIterator& operator--();
MyIterator operator--(int);
MyIterator& operator+=(int);
MyIterator& operator-=(int);
friend auto operator<=>(MyIterator, MyIterator) = default;
friend int operator-(MyIterator, MyIterator);
friend MyIterator operator+(MyIterator, int);
friend MyIterator operator-(MyIterator, int);
friend MyIterator operator+(int, MyIterator);
};

static_assert(std::contiguous_iterator<MyIterator>); // OK!

另外,我看到了一些关于使用成员 typedef iterator_concept 的内容。而不是 iterator_category .我为什么要提供 MyIterator::iterator_concept ? (我不是在这里要求完整的历史解释;只是一个简单的最佳实践指南“不要忘记 iterator_concept”或“是的,因为它有助于 X”会很好。)

最佳答案

C++ 概念作为语言特性的主要好处之一是概念定义告诉您需要提供什么。 std::contiguous_iterator is no different .是的,您可能需要深入研究 10 多个其他概念定义层才能深入了解您需要提供的基本术语。但它们就在语言中。
简而言之,连续迭代器是随机访问迭代器:

  • 其标签源自 contiguous_iterator
  • 谁的reference_type是对其 value_type 的左值引用(即:不是代理迭代器或生成器)。
  • standard library function std::to_address 可以被调用以将任何有效的迭代器(即使是不可解引用的)转换为指向迭代器引用的元素或指向最后一个指针的指针。

  • 不幸的是,满足 #3 不能通过特化来完成 std::to_address直接地。您必须使用专业 pointer_traits::to_address为您的迭代器类型或给您的迭代器一个 operator->重载。
    后者更容易做到,尽管 operator-> std::contiguous_iterator 没有其他要求, 对于这样的迭代器类型是有意义的:
    class MyIterator
    {
    ...
    int const *operator->() const;
    };

    仅供引用:如果您基于概念约束模板,而不仅仅是 static_assert,大多数编译器会给您更多有用的错误消息。正在研究它。像这样:
    template<std::contiguous_iterator T>
    void test(const T &t);

    test(MyIterator{});

    关于c++ - 在 C++20 中,如何编写连续迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65712091/

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