テンプレート関数の部分的特殊化
テンプレート関数の部分的特殊化
問
テンプレート関数において、特定のテンプレートパラメータの時、当初のテンプレート関数と違う処理をしたい場合、どうすればよいのだろうか?
前提
- 部分的な特殊化はクラスの場合可能
//元となるクラステンプレート template<typename T, typename U> class Myclass{ }; //TがFoo の場合、元のクラステンプレートとは別の処理をしたい template<typename U> class Myclass<Foo, U>{ //別処理 };
- 関数だと部分的特殊化(注)はできない。
注 全てのテンプレートパラメータを指定する明示的な特殊化は可
//元 template<typename T, typename U> T* Create(const U& arg){ return new T(arg); } // TがFoo型の場合、元と別の処理がしたい template<typename U> Foo* Create<Foo, U>(U& arg){ return new Foo(arg, 1); } //このコードは許されていない。
解決
- 関数のオーバーロード利用する
- 型情報を伝達できる型の生成
//元 template<typename T, typename U> T* Create(const U& arg, T){ return new T(arg); }; //TがFooの場合特別な処理 template<typename U> T* Create(const U& arg, Foo){ return new Foo(arg, 1); };
ただし、これではT、Fooの一時変数が発生していしまい、オーバーヘッドに!
ここでオーバーヘッドが発生せず、型情報を伝える方法が必要
// 型情報を伝えるためのclass template<typename T> class Type2Type{ typedef T Originaltype; }; //元 template<typename T, typename U> T* Create(const U& arg,Type2Type<T>){ return new T(arg); } // UがFooの場合、特別な処理 template<typename T> Foo* Create(const U& arg, type2Type<Foo>{ return Foo(arg, 1); } //Createの使用方法 //元のCreateを利用 std::string pStr=Create("Hello", Type2Type<std::string>()}; //FooのCreateを利用 Foo* pF=Create(100, Type2Type<Foo>()};