スポンサーリンク

typetraitsのstd::is_base_ofにパラメータパックを入れられるare_derived_fromを作る

下記のように、パラメータパックで入ってきたクラス全部が特定のクラスの子であることをチェックしたい。探したが見つからなかったので自分で作る。

// OK
template<class Base,class Class>
class MyClass {
  static_assert(std::is_base_of<Base, Class>::value, " Class is invalid");
};

// NG
template<class Base, class... Classes>
class MyClass2 {
  static_assert(std::is_base_of<Base, Classes...>::value, " Class are invalid");
};

まず、以下のようにテスト用のクラスを定義しておく。

class MyBase {
  int a;
};
class MyDeri1 :public MyBase{
  int b;
};
class MyDeri2 :public MyBase {
  int c;
};
class Independent{
  int d;
};

次に、そもそもstd::is_base_ofのvalueが型としては何なのかを知りたいので、以下のようにチェックする。

  std::cout << 
    std::is_base_of<
      std::true_type, 
      std::is_base_of<MyBase, MyDeri1>>::value;

出力:

1

と、std::is_base_ofは最終的にはstd::true_typeかstd::false_typeになることが分かったので、それと同じようになるようにare_derived_fromも実装する。are_derived_fromが英語的にどうかは知らい。

template<class Base, class CHead, class ...Classes>
struct are_derived_from : public
  std::conditional<
    std::is_base_of<Base, CHead>::value,  //CHeadに対して評価
      are_derived_from<Base, Classes...>, // 上評価がtrueならそれ以外の型についても調べる
      std::false_type                       // 一つでもfalseなら全部falseになる
  >::type
{
};


//末尾の特殊化
template<class Base, class CTail>
struct are_derived_from<Base, CTail> : public std::is_base_of<Base, CTail>
{
};

使用例

int main()
{

  std::cout << are_derived_from<MyBase, MyDeri1, MyDeri2>::value << std::endl;
  std::cout << are_derived_from<MyBase, MyDeri1, Independent>::value << std::endl;

}

出力:

1
0

 

 

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: