web-dev-qa-db-ja.com

なぜstd :: iteratorは非推奨なのですか?

テンプレートクラス std::iterator は、C++ 17で非推奨に設定されています。なぜそうなのか? std::iterator_traits は、特にデフォルトのテンプレート引数を使用できる場合に機能します。 C++ 17でそれを行う他の方法はありますか?

37
aschepler

廃止を提案した提案 から:

イテレータクラスの記述を支援するために、元の標準ライブラリは、イテレータクラステンプレートを提供して、iterator_traitsによってすべてのイテレータに期待される5つのtypedefの宣言を自動化しました。これは、ライブラリー自体で、たとえばstd::ostream_iteratorの仕様で使用されました。

template <class T, class charT = char, class traits = char_traits<charT> >
class ostream_iterator:
  public iterator<output_iterator_tag, void, void, void, void>;

void引数の長いシーケンスは、クラス定義自体で予想されるtypedefを単に提供するよりもはるかに明確ではありません。これは、C++ 14で設定されたパターンに従って、現在の作業ドラフトで採用されているアプローチですunary_functionおよびbinary_functionからのファンクターのライブラリ全体での派生を廃止しました。

明確さの低下に加えて、イテレータテンプレートは、通常の使用法では依存する基本クラスであるため、不注意のためのトラップも配置します。これは、クラスまたはそのメンバー関数内からの名前検索中に調べないことを意味します。これは、次の単純な使用法が機能しない理由を理解しようとする驚きのユーザーにつながります。

#include <iterator>

template <typename T>
struct MyIterator : std::iterator<std::random_access_iterator_tag, T> {
   value_type data;  // Error: value_type is not found by name lookup 

   // ... implementations details elided ...
};

明確さだけの理由で、LWGが標準ライブラリ仕様を更新して、std::iteratorに由来するものとして標準イテレータアダプターを必須にしないように説得するのに十分であったため、標準自体ではこのテンプレートを使用しません。したがって、非推奨の強力な候補のようです。

LWG 2438 でSTLの推論を確認することもできます。 (h/t T.C。


他の方法については、そうではありません。基本的に、独自のバージョンのstd::iterator(それほど難しくない)を実装するか、すべてのtypedefを手動で書き出すことができます(どちらもそれほど難しくありません。実際、わかりやすくするためにそれを好みます)。

26
Barry