最終更新日時: 2025年07月10日 10時26分30秒 (JST)
Koichi Murase が更新

履歴 編集

# エイリアステンプレート経由でのクラステンプレートのテンプレート引数推論 [P1814R0](C++20)

このページはC++20に採用された言語機能の変更を解説しています。

のちのC++規格でさらに変更される場合があるため関連項目を参照してください。

## 概要

C++17で導入されたクラステンプレートのテンプレート引数推論は、コンストラクタ引数からテンプレート引数を推論するものであった。しかし、そのクラステンプレートのエイリアステンプレートを定義した場合に、エイリアステンプレートの変数定義からはクラステンプレートのテンプレート引数を推論できない問題があった。

C++20では、エイリアステンプレートからでもコンストラクタ引数からクラステンプレート引数を推論できるようになる。

    template <class T>
    struct Point {
      T x;
      T y;

      Point(T x_, T y_)
        : x(x_), y(y_) {}
    };

    template <class T>
    using MyPoint = Point<T>;

    MyPoint p1{3.0, 4.0}; // C++17:NG C++20:OK

エイリアステンプレート側で制約を課した場合：

    #include <concepts>
    #include <type_traits>

    template <class T, class U>
    struct C {
      C(T, U);                                // #1
    };

    template <class T, class U>
    C(T, U) -> C<T, std::type_identity_t<U>>; // #2

    // 2つのテンプレート引数を同じ型、かつポインタ型に限定する
    template <class V>
    using A = C<V*, V*>;

    // 2つのテンプレート引数を同じ型、かつ整数のポインタ型に限定する
    template <std::integral W>
    using B = A<W>;

    int i{};
    double d{};

    A a1(&i, &i); // A<int>に推論される
    A a2(i, i);   // エラー！ iからV*を推論できない (ポインタ型でないといけない)
    A a3(&i, &d); // エラー！
                  // #1: (int *, double *)から(V*, V*)を推論できない
                  // #2: C<int *, double *>からA<V>を推論できない

    B b1(&i, &i); // B<int>に推論される
    B b2(&d, &d); // エラー！ C<double*, double*>からB<W>を推論できない
                  // (整数のポインタ型でないといけない)

## 関連項目

- C++17 クラステンプレートのテンプレート引数推論

## 参照

- P1814R0 Wording for Class Template Argument Deduction for Alias Templates