最終更新日時(UTC):
が更新

履歴 編集

非型テンプレートパラメータとしてクラス型を許可する(C++20)

概要

これまで、非型テンプレートパラメータ (non-type template parameter) としては、整数型、ポインタ、参照、std::nullptr_tプレースホルダ型の値しか受け取ることが許可されていなかった。

template <int N>
class X;

X<3> x;

C++11以降での汎用的な定数式constexprの導入により、多くのクラスオブジェクトを定数として扱えるようになったことを受けて、C++20ではそのように定数として扱える型を広く非型テンプレートパラメータとして受け取ることが許可される。

仕様

非型テンプレートパラメータとして、以下のいずれかに分類される型のオブジェクトを受け取ることができる:

  • 構造的型
  • プレースホルダ型を含む型 (template <auto V> class X;auto)
  • 推論用クラス型のプレースホルダ (template <class T> A;があったときのA x{};のようなクラステンプレートのテンプレート引数推論を意図した型指定)

構造的型 (structural type) とは以下のいずれかに分類される型である:

  • スカラ型
  • 左辺値参照型
  • 以下の特徴をもつリテラルクラス型:
    • すべての基本クラスと非静的メンバ変数がpublicかつ非mutableであり、
    • すべての基本クラスと非静的メンバ変数が構造的型もしくはその (多次元) 配列である

struct X1 {
  int i;
  float f;

  friend bool operator==(const X1&, const X1&) = default;
};

struct X2 {
  int i;
  float f;

  constexpr X2(int i_, float f_)
    : i(i_), f(f_) {}

  friend bool operator==(const X2&, const X2&) = default;
};

template <int N>
struct C1 {
  static constexpr int value = N;
};

template <float N>
struct C2 {
  static constexpr float value = N;
};

template <X1 x1, X2 x2>
struct C3 {
  static constexpr X1 value1 = x1;
  static constexpr X2 value2 = x2;
};

template <auto V>
struct C4 {
  static constexpr decltype(V) value = V;
};

int main() {
  static_assert(C1<1>::value == 1);
  static_assert(C2<3.14f>::value == 3.14f);

  constexpr X1 x1{1, 3.14f};
  constexpr X2 x2{2, 5.27f};
  using c3 = C3<x1, x2>;
  static_assert(c3::value1 == x1);
  static_assert(c3::value2 == x2);

  static_assert(C4<1>::value == 1);
  static_assert(C4<3.14f>::value == 3.14f);
  static_assert(C4<x1>::value == x1);
  static_assert(C4<x2>::value == x2);

  constexpr std::pair p{1, 3.14};
  static_assert(C<p>::value == p);
}

出力

備考

関連項目

参照