テンプレート関数の部分的特殊化

テンプレート関数の部分的特殊化

テンプレート関数において、特定のテンプレートパラメータの時、当初のテンプレート関数と違う処理をしたい場合、どうすればよいのだろうか?

前提

  • 部分的な特殊化はクラスの場合可能
//元となるクラステンプレート
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>()};

詳細:Modern C++ Design