1

次のようなテンプレート関数を記述する場合:

template<class T> void print(T const & collection)

コレクションをループしてイテレータを逆参照するとき、vector<int>に変更しない限り、次のようなものがあればすべて正常に機能しますvector<int*>。コードを複製せずに、単一のテンプレート関数の違いに対処する最善の方法は何ですか?

4

1 に答える 1

0

do_printクラス template に委譲する単一のテンプレート関数を作成しprinterます。クラス テンプレートは、プリティ プリントを行う関数オブジェクトであり、 でT*プリティ プリント バージョンを呼び出すだけで部分的に特殊化できます*t

そのため、プリティ プリンティング コードの重複はなく、2 つの軽量実装クラスを作成する際の多少の不都合はありません (これらは最新のコンパイラによって最適化されるため、実行時のオーバーヘッドはありません)。

私は、SFINAE トリックよりもこのソリューションを好みます。なぜなら、部分的なクラスの特殊化は、関数オーバーロードのトリックよりもはるかに多くの制御 (およびより適切なエラー メッセージ) を提供するからです。Alexandrescu & Sutter Coding Standards でも推奨されています。

ところで、このコードは にも機能T**T*ますT。sendも同様で、最終的に にT**送信されます。実際、任意のレベルの間接化は、ポインターが指す要素を出力することになります。T*T

#include <iostream>
#include <vector>

namespace detail {

template<typename T>
struct printer
{
   void operator()(T const& t) 
   { 
      std::cout << t; // your pretty print code here
   }  
};

template<typename T>
struct printer<T*>
{
   void operator()(T const* t) 
   { 
      printer<T>()(*t); // delegate to printing elements (no duplication of prettty print)
   }
};

}

template<typename T>
void do_print(T const& t)
{
   detail::printer<T>()(t);
}

template<typename C>
void print(C const& collection)
{
   for(auto&& c: collection) 
      do_print(c);
   std::cout << "\n";
}

int main()
{
   int a = 1;
   int b = 2;

   auto c = &a;
   auto d = &b;

   std::vector<int> v1 { a, b };
   std::vector<int*> v2 { c, d };
   std::vector<int**> v3 { &c, &d };

   print(v1);
   print(v2);
   print(v3);
}

ライブワークスペースへの出力

于 2013-01-14T10:18:30.327 に答える