为了便于讨论,我们假设我们有一个完全符合C++20的库实现。我想编写尽可能最简单的连续迭代器。
#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!
这是我应该做的吗?感觉非常刺耳。(需要说明的是:我的第一次尝试失败也感觉非常麻烦。)
我是不是错过了一些更简单的方式?
具体地说,MyIterator本身有没有办法保证它是连续的,只使用可以在类主体中定义的成员和朋友以及其他东西?比如,如果MyIterator是在某个深度嵌套的命名空间中定义的,我不想为了打开namespace std而一直中断到顶层命名空间。编辑后添加:Glen Fernandes告诉我有一种更简单的方法--我只需添加一个element_type类型定义,like this!(并且我可以在C++20中删除iterator_traits‘5个较大的类型定义中的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); }; static_assert(std::contiguous_iterator<MyIterator>); // OK!
此外,我还看到了一些关于使用成员tyecifiterator_concept而不是iterator_category的内容。我为什么要提供MyIterator::iterator_concept?(我在这里并不要求完整的历史解释;我只是要求一个简单的最佳实践指导方针,忘掉iterator_concept或是的,提供它,因为它有助于X&q;将会很好。)