可変長引数テンプレートクラスのテスト。以下のテンプレートクラスは、
第一テンプレート引数で指定した型の派生型を
第二以降テンプレート引数から探して返す。
#include <iostream>
///////////////////////////////////////////////////////// ///////////////////////////////////////////////////////// // テスト用のクラス一覧 class AAA { public: void print() { std::cout << "AAA" << std::endl;} }; class BBB { public: void print() { std::cout << "BBB" << std::endl;} }; class CCC { public: void print() { std::cout << "CCC" << std::endl;} }; class AAADerived :public AAA { public: void print() { std::cout << "AAADerived" << std::endl; } }; class CCCDerived :public CCC { public: void print() { std::cout << "CCCDerived" << std::endl; } }; class DUMMY { public: void print() { std::cout << "指定されていません" << std::endl; } };///////////////////////////////////////////////////////// ///////////////////////////////////////////////////////// // クラス選択クラスの本体 template<class Base,class Head, class... Args> struct Search { using type_t = typename std::conditional < std::is_base_of<Base, Head>::value, //判断 Head, typename Search<Base, Args...>::type_t>::type; };// クラス選択クラスの本体(特殊化)
template<class Base, class Head> struct Search<Base,Head> { using type_t = typename std::conditional < std::is_base_of<Base, Head>::value, //判断 Head, DUMMY>::type; }; ///////////////////////////////////////////////////////// ///////////////////////////////////////////////////////// // クラス選択クラス // 第一テンプレート引数に指定したクラスから派生したクラスを、 // 第二以降テンプレート引数から選択する template<class Base, class... Args> struct TypeDerived { using type_t = typename Search<Base,Args...>::type_t; };//////////////////////////////////////////////////////// //////////////////////////////////////////////////////// // 動作確認 int main() { using T = TypeDerived< AAA,//このクラスの派生クラスを探す BBB, CCCDerived, AAADerived >::type_t; T obj; obj.print(); int i; std::cin >> i; }
普通の感覚だとこんなもんどこに使い道があるのかわからないので使用例を置いておくと、以下のABCクラスでは、AAA,BBB,CCC(及びその派生クラス)をどんな順番で指定してもちゃんと動作する。普通テンプレートに指定する型の順番は(当たり前だが)決まっている。だから何だといわれると困るのでもう一つ、クラス指定が足りなかった場合も、自動的にDUMMYが指定されるのでエラーにならない。
template<class... T> class ABC { public: typename TypeDerived<AAA, T...>::type_t a; typename TypeDerived<BBB, T...>::type_t b; typename TypeDerived<CCC, T...>::type_t c; }; int main() { std::cout << "obj1 ------" << std::endl; ABC<AAA, CCCDerived,BBB> obj1; obj1.a.print(); obj1.b.print(); obj1.c.print(); std::cout << std::endl; std::cout << "obj2 ------" << std::endl; ABC<BBB, CCC, AAADerived> obj2; obj2.a.print(); obj2.b.print(); obj2.c.print(); std::cout << std::endl; std::cout << "obj3 ------" << std::endl; ABC<AAADerived, BBB> obj3; obj3.a.print(); obj3.b.print(); obj3.c.print(); std::cout << std::endl; int i; std::cin >> i; }
obj1 ------
AAA
BBB
CCCDerived
obj2 ------
AAADerived
BBB
CCC
obj3 ------
AAADerived
BBB
指定されていません