3月21日st 標準化委員会は、 std::iterator
の非推奨を承認するために投票しました P0174 で提案:
Void引数の長いシーケンスは、クラス定義自体で予想される
typedef
sを単に提供するよりもはるかに明確ではありません。これは、 c ++ 14
c ++ 17 からの継承std::iterator
からの継承は、イテレータの定型的な実装から退屈なものを削除することが推奨されていました。ただし、非推奨には次のいずれかが必要です。
typedef
sを含める必要がありますauto
を使用する必要がありますstd::iterator_traits
は、std::iterator
から継承せずに動作するように更新される可能性があるc ++ 17 互換性を念頭に置いてカスタムイテレータを設計しているため、これらのオプションのどれを期待すべきかを誰かに教えてもらえますか?
議論された代替案は明確ですが、コード例が必要だと感じています。
言語の代替がなく、ブーストまたはイテレータ基本クラスの独自バージョンに依存しない場合、std::iterator
を使用する次のコードは、その下のコードに修正されます。
std::iterator
を使用template<long FROM, long TO>
class Range {
public:
// member typedefs provided through inheriting from std::iterator
class iterator: public std::iterator<
std::forward_iterator_tag, // iterator_category
long, // value_type
long, // difference_type
const long*, // pointer
const long& // reference
>{
long num = FROM;
public:
iterator(long _num = 0) : num(_num) {}
iterator& operator++() {num = TO >= FROM ? num + 1: num - 1; return *this;}
iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
bool operator==(iterator other) const {return num == other.num;}
bool operator!=(iterator other) const {return !(*this == other);}
long operator*() {return num;}
};
iterator begin() {return FROM;}
iterator end() {return TO >= FROM? TO+1 : TO-1;}
};
( http://en.cppreference.com/w/cpp/iterator/iterator からのコード。元の著者の許可を得て)。
std::iterator
なしtemplate<long FROM, long TO>
class Range {
public:
class iterator {
long num = FROM;
public:
iterator(long _num = 0) : num(_num) {}
iterator& operator++() {num = TO >= FROM ? num + 1: num - 1; return *this;}
iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
bool operator==(iterator other) const {return num == other.num;}
bool operator!=(iterator other) const {return !(*this == other);}
long operator*() {return num;}
// iterator traits
using difference_type = long;
using value_type = long;
using pointer = const long*;
using reference = const long&;
using iterator_category = std::forward_iterator_tag;
};
iterator begin() {return FROM;}
iterator end() {return TO >= FROM? TO+1 : TO-1;}
};
オプション3は、すべて同じtypedefs
を記述する必要がありますが、さらに_iterator_traits<X>
_をラップする必要があるため、オプション1の厳密に型指定されたバージョンです。
オプション2はソリューションとしては実行不可能です。一部の型を推測できます(たとえば、reference
はdecltype(*it)
だけです)が、_iterator_category
_を推測することはできません。イテレータがマルチパス保証を満たしているかどうかを再帰的に確認できないため、単にオペレーションの存在だけで_input_iterator_tag
_と_forward_iterator_tag
_を区別できません。さらに、イテレータが可変参照を生成する場合、これらと_output_iterator_tag
_を実際に区別することはできません。どこかに明示的に提供する必要があります。
これでオプション1は終了します。すべての定型文を書くことに慣れる必要があると思います。私は、新しい手根管の支配者を歓迎します。