私は、C ++の非メンバー関数は、引数のタイプに基づいてディスパッチしないという(おそらく間違った)仮定の下にありました。しかし、それについて読んだ後iterator_category
、引数のカテゴリタイプに応じて関数を呼び出すことができ、その呼び出しは継承も処理するようです。たとえば、ランダムアクセスイテレータと入力イテレータの実装のみを記述した場合、非ランダムアクセスイテレータを使用したすべての呼び出しは、入力イテレータを受け入れる関数に移動します。これは本からの短縮例です
template <class T>
foo(T a) {
foo(a, iterator_traits<T>::iterator_category());
}
template <class T>
foo(T a, random_access_iterator_tag) { \\body}
template <class T>
foo(T a, input_iterator_tag) { \\body}
// presumably this works even for
// ostream_iterator<int> i(cout);
// foo(i);
この種のディスパッチは一般的に正しいですか、それともこれは特殊なケースですか?
たとえば、イテレータカテゴリベースの例で、ランダムアクセスイテレータと双方向イテレータのみの実装を指定した場合、コンパイラが出力イテレータがカバーされていないと文句を言った場合、コンパイラは実装が網羅的でない場合に警告することになっていますか?
また、オブジェクト/インスタンスではなく、型のみの引数を持つ関数に遭遇したのはこれが初めてです。では、その型のインスタンス/オブジェクトの名前を指定せずに、引数の1つとして組み込み型またはユーザー定義型の関数を定義できますか?
以下は、コンパイル時のポリモーフィズムを実現するためのCRTPの代替手段のようです。それは正しい解釈ですか
template<class T>
int foo(T a) {
foo(a, a::type());
}
int foo(int a, base) { \\body }
int foo(int a, derived) { \\body }