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

履歴 編集

function
<tuple>

std::tuple::コンストラクタ(C++11)

constexpr tuple();                                        // (1) C++11
EXPLICIT constexpr tuple();                               // (1) C++17
explicit(see below) constexpr tuple();                    // (1) C++20

explicit tuple(const Types&...);                          // (2) C++11
constexpr explicit tuple(const Types&...);                // (2) C++14
EXPLICIT constexpr tuple(const Types&...);                // (2) C++17
explicit(see below) constexpr tuple(const Types&...);     // (2) C++20

template <class... UTypes>
explicit tuple(UTypes&&...);                              // (3) C++11
template <class... UTypes>
constexpr explicit tuple(UTypes&&...);                    // (3) C++14
template <class... UTypes>
EXPLICIT constexpr tuple(UTypes&&...);                    // (3) C++17
template <class... UTypes>
explicit(see below) constexpr tuple(UTypes&&...);         // (3) C++20

tuple(const tuple&) = default;                            // (4) C++11
tuple(tuple&&) = default;                                 // (5) C++11

template<class... UTypes>
explicit(see below) constexpr tuple(tuple<UTypes...>&);   // (6) C++23

template <class... UTypes>
tuple(const tuple<UTypes...>&);                           // (7) C++11
template <class... UTypes>
constexpr tuple(const tuple<UTypes...>&);                 // (7) C++14
template <class... UTypes>
EXPLICIT constexpr tuple(const tuple<UTypes...>&);        // (7) C++17
template <class... UTypes>
explicit(see below) constexpr
  tuple(const tuple<UTypes...>&);                         // (7) C++20

template <class... UTypes>
tuple(tuple<UTypes...>&&);                                // (8) C++11
template <class... UTypes>
constexpr tuple(tuple<UTypes...>&&);                      // (8) C++14
template <class... UTypes>
EXPLICIT constexpr tuple(tuple<UTypes...>&&);             // (8) C++17
template <class... UTypes>
explicit(see below) constexpr tuple(tuple<UTypes...>&&);  // (8) C++20

template<class... UTypes>
explicit(see below) constexpr 
  tuple(const tuple<UTypes...>&&);                        // (9) C++23

template<class U1, class U2>
explicit(see below) constexpr tuple(pair<U1, U2>&);       // (10) C++23

template <class U1, class U2>
tuple(const pair<U1, U2>&);                               // (11) C++11
template <class U1, class U2>
constexpr tuple(const pair<U1, U2>&);                     // (11) C++14
template <class U1, class U2>
EXPLICIT constexpr tuple(const pair<U1, U2>&);            // (11) C++17
template <class U1, class U2>
explicit(see below) constexpr tuple(const pair<U1, U2>&); // (11) C++20

template <class U1, class U2>
tuple(pair<U1, U2>&&);                                    // (12) C++11
template <class U1, class U2>
constexpr tuple(pair<U1, U2>&&);                          // (12) C++14
template <class U1, class U2>
EXPLICIT constexpr tuple(pair<U1, U2>&&);                 // (12) C++17
template <class U1, class U2>
explicit(see below) constexpr tuple(pair<U1, U2>&&);      // (12) C++20

template<class U1, class U2>
explicit(see below) constexpr
  tuple(const pair<U1, U2>&&);                            // (13) C++23

template<tuple-like UTuple>
  explicit(see below) constexpr tuple(UTuple&&);          // (14) C++23


// 以下アロケータを指定する構築
template <class Alloc>
tuple(allocator_arg_t, const Alloc& a);                   // (15) C++11
template <class Alloc>
explicit(see below) constexpr 
  tuple(allocator_arg_t, const Alloc& a);                 // (15) C++20

template <class Alloc>
tuple(allocator_arg_t,
      const Alloc& a,
      const Types&...);                                   // (16) C++11
template <class Alloc>
EXPLICIT tuple(allocator_arg_t,
               const Alloc& a,
               const Types&...);                          // (16) C++17
template <class Alloc>
explicit(see below) constexpr tuple(allocator_arg_t,
                                    const Alloc& a,
                                    const Types&...);     // (16) C++20

template <class Alloc, class... UTypes>
tuple(allocator_arg_t,
      const Alloc& a,
      UTypes&&...);                                       // (17) C++11
template <class Alloc, class... UTypes>
EXPLICIT tuple(allocator_arg_t,
               const Alloc& a,
               UTypes&&...);                              // (17) C++17
template <class Alloc, class... UTypes>
explicit(see below) constexpr tuple(allocator_arg_t,
                                    const Alloc& a,
                                    UTypes&&...);         // (17) C++20

template <class Alloc>
tuple(allocator_arg_t,
      const Alloc& a,
      const tuple&);                                      // (18) C++11
template <class Alloc>
constexpr tuple(allocator_arg_t,
                const Alloc& a,
                const tuple&);                            // (18) C++20

template <class Alloc>
tuple(allocator_arg_t,
      const Alloc& a,
      tuple&&);                                           // (19) C++11
template <class Alloc>
constexpr tuple(allocator_arg_t,
                const Alloc& a,
                tuple&&);                                 // (19) C++20

template<class Alloc, class... UTypes>
explicit(see below) constexpr
  tuple(allocator_arg_t,
        const Alloc& a, 
        tuple<UTypes...>&);                               // (20) C++23

template <class Alloc, class... UTypes>
tuple(allocator_arg_t,
      const Alloc& a,
      const tuple<UTypes...>&);                           // (21) C++11
template <class Alloc, class... UTypes>
EXPLICIT tuple(allocator_arg_t,
               const Alloc& a,
               const tuple<UTypes...>&);                  // (21) C++17
template <class Alloc, class... UTypes>
explicit(see below) constexpr
  tuple(allocator_arg_t,
        const Alloc& a,
        const tuple<UTypes...>&);                         // (21) C++20

template <class Alloc, class... UTypes>
tuple(allocator_arg_t,
      const Alloc& a,
      tuple<UTypes...>&&);                                // (22) C++11
template <class Alloc, class... UTypes>
EXPLICIT tuple(allocator_arg_t,
               const Alloc& a,
               tuple<UTypes...>&&);                       // (22) C++17
template <class Alloc, class... UTypes>
explicit(see below) constexpr
  tuple(allocator_arg_t,
        const Alloc& a,
        tuple<UTypes...>&&);                              // (22) C++20

template<class Alloc, class... UTypes>
explicit(see below) constexpr
  tuple(allocator_arg_t,
        const Alloc& a,
        const tuple<UTypes...>&&);                        // (23) C++23

template<class Alloc, class U1, class U2>
explicit(see below) constexpr
  tuple(allocator_arg_t,
        const Alloc& a, 
        pair<U1, U2>&);                                   // (24) C++23

template <class Alloc, class U1, class U2>
tuple(allocator_arg_t,
      const Alloc& a,
      const pair<U1, U2>&);                               // (25) C++11
template <class Alloc, class U1, class U2>
EXPLICIT tuple(allocator_arg_t,
               const Alloc& a,
               const pair<U1, U2>&);                      // (25) C++17
template <class Alloc, class U1, class U2>
explicit(see below) constexpr
  tuple(allocator_arg_t,
        const Alloc& a,
        const pair<U1, U2>&);                             // (25) C++20

template <class Alloc, class U1, class U2>
tuple(allocator_arg_t,
      const Alloc& a,
      pair<U1, U2>&&);                                    // (26) C++11
template <class Alloc, class U1, class U2>
EXPLICIT tuple(allocator_arg_t,
               const Alloc& a,
               pair<U1, U2>&&);                           // (26) C++17
template <class Alloc, class U1, class U2>
explicit(see below) constexpr
  tuple(allocator_arg_t,
        const Alloc& a,
        pair<U1, U2>&&);                                  // (26) C++20

template<class Alloc, class U1, class U2>
explicit(see below) constexpr
  tuple(allocator_arg_t,
        const Alloc& a, 
        const pair<U1, U2>&&);                            // (27) C++23

template<class Alloc, tuple-like UTuple>
explicit(see below) constexpr
  tuple(allocator_arg_t, const Alloc& a, UTuple&&);       // (28) C++23

tupleオブジェクトの構築

  • (1) : デフォルトコンストラクタ(すべての要素を初期化して構築)
  • (2) : 可変テンプレートパラメータの型の値によるコピー構築
  • (3) : 可変テンプレートパラメータの型に変換可能な値によるムーブ構築
  • (4) : コピーコンストラクタ
  • (5) : ムーブコンストラクタ
  • (6)-(9) : 変換可能な他のtupleオブジェクトから構築
    • (6), (7), (9) はコピー構築、(8) はムーブ構築される
  • (10)-(13) : テンプレートパラメータ数が2の場合、std::pairオブジェクトから構築する
    • (10), (11), (13) はコピー構築、(12) はムーブ構築される
  • (14) : tuple-likeなオブジェクトから構築する

以下 (15)-(28) は (1)-(14) のアロケータ指定版であり、アロケータを指定する事以外は (1)-(14) と等価である。

  • (15) : アロケータを指定してデフォルト構築する
  • (16) : アロケータを指定して可変テンプレートパラメータの型の値によってコピー構築する
  • (17) : アロケータを指定して可変テンプレートパラメータの型の値によってムーブ構築する
  • (18) : アロケータを指定してコピー構築
  • (19) : アロケータを指定してムーブ構築
  • (20)-(23) : アロケータを指定して変換可能な他のtupleオブジェクトから構築
    • (20), (21), (23) はコピー構築、(22) はムーブ構築される
  • (24)-(27) : テンプレートパラメータ数が2の場合、アロケータを指定してstd::pairオブジェクトから構築する
    • (24), (25), (27) はコピー構築、(26) はムーブ構築される
  • (28) : アロケータを指定してtuple-likeなオブジェクトから構築する

テンプレートパラメータ制約

  • (1), (15) :
  • (2), (16) :
  • (3), (17) :
  • (4), (18) :
  • (5), (19) :
  • (6)-(9), (20)-(23) :
    • Iをパラメータパック0, 1, ..., (sizeof...(Types) - 1)FWD(u)static_cast<decltype(u)>(u)sizeof...(Types) == 1の場合は、Types...Tへ、UTypes...Uへ展開したと定義して
    • C++23 : sizeof...(Types) == sizeof...(UTypes) && (is_constructible_v<Types, decltype(get<I>(FWD(u)))> && ...) == trueであること
    • C++23 : 更に、sizeof...(Types) != 1または、is_convertible_v<decltype(u), T> == false && is_constructible_v<T, decltype(u)> == false && is_same_v<T, U> == falseであること
  • (7), (21) :
    • sizeof...(Types) == sizeof...(UTypes)であること
    • Types...の全ての型Tiと、UTypes...の全ての型Uiについて、is_constructible<Ti, const Ui&>::value == trueであること
    • C++17 : sizeof(Types...) != 1であるか、そうでなければTypes...の先頭をTUTypes...の先頭をUとして、!is_convertible_v<const tuple<U>&, T> && !is_constructible_v<T, const tuple<U>&> && !is_same_v<T, U>trueであること
      • コピーコンストラクタとのオーバーロードが成立することを意図している
    • C++23 : (6)-(9), (20)-(23) の定義参照
  • (8), (22) :
    • sizeof...(Types) == sizeof...(UTypes)であること
    • Types...の全ての型Tiと、UTypes...の全ての型Uiについて、is_constructible<Ti, Ui&&>::value == trueであること
    • C++17 : sizeof(Types...) != 1であるか、そうでなければTypes...の先頭をTUTypes...の先頭をUとして、!is_convertible_v<tuple<U>, T> && !is_constructible_v<T, tuple<U>> && !is_same_v<T, U>trueであること
      • ムーブコンストラクタとのオーバーロードが成立することを意図している
    • C++23 : (6)-(9), (20)-(23) の定義参照
  • (10)-(13), (24)-(27) :
    • FWD(u)static_cast<decltype(u)>(u)Types...の0番目の型をT0、1番目の型をT1であるとして、
    • C++23 : sizeof...(Types) == 2であること
    • C++23 : is_constructible_v<T0, decltype(get<0>(FWD(u))) == trueであること
    • C++23 : is_constructible_v<T1, decltype(get<1>(FWD(u))) == trueであること
  • (11), (25) :
    • Types...の0番目の型をT0、1番目の型をT1であるとする
    • sizeof...(Types) == 2であること
    • is_constructible<T0, const U1&>::value == trueかつis_constructible<T1, const U2&>::value == trueであること
    • C++23 : (10)-(13), (24)-(27) の定義参照
  • (12), (26) :
    • Types...の0番目の型をT0、1番目の型をT1であるとする
    • sizeof...(Types) == 2であること
    • is_constructible<T0, U1&&>::value == trueかつis_constructible<T1, U2&&>::value == trueであること
    • C++23 : (10)-(13), (24)-(27) の定義参照
  • (14), (28) :

備考

  • (1) :
    • C++17 : Types...のうちいずれかの型が非暗黙にデフォルト構築できる場合、この関数はexplicitとなる
  • (2) :
    • C++11からC++14まで : 無条件でexplicitとなる
    • C++17から : !conjunction_v<is_convertible<const Types&, Types>...>である場合、この関数はexplicitとなる
  • (3) :
  • (6)-(9) :
    • Iをパラメータパック0, 1, ..., (sizeof...(Types) - 1)FWD(u)static_cast<decltype(u)>(u)と定義して、
    • C++23 : !(is_convertible_v<decltype(get<I>(FWD(u))), Types> && ...)である場合、この関数はexplicitとなる
    • C++23 : (reference_constructs_from_temporary_v<Types, decltype(get<I>(FWD(u)))> || ...)である場合、この関数は削除定義される
  • (7) :
    • C++17 : !conjunction_v<is_convertible<const Types&, Types>...>である場合、この関数はexplicitとなる
    • C++23 : (6)-(9) の定義参照
  • (8) :
    • C++17 : !conjunction_v<is_convertible<UTypes&&, Types>...>である場合、この関数はexplicitとなる
    • C++23 : (6)-(9) の定義参照
  • (10)-(13) :
  • (11) :
    • Types...の0番目の型をT0、1番目の型をT1であるとする
    • C++17 : !is_convertible_v<const U1&, T0> || !is_convertible_v<const U2&, T1>である場合、この関数はexplicitとなる
    • C++23 : (10)-(13) の定義参照
  • (12) :
    • Types...の0番目の型をT0、1番目の型をT1であるとする
    • C++17 : !is_convertible_v<U1&&, T0> || !is_convertible_v<U2&&, T1>である場合、この関数はexplicitとなる
    • C++23 : (10)-(13) の定義参照
  • (14) :
    • Iをパラメータパック0, 1, ..., (sizeof...(Types) - 1)と定義して、
    • C++23 : !(is_convertible_v<decltype(get<I>(std::forward<UTuple>(u))), Types> && ...)である場合、この関数はexplicitとなる
  • (15) :
    • C++20 : 対応するコンストラクタ (1) と同じ条件でexplicitとなる
  • (16) :
    • C++17 : 対応するコンストラクタ (2) と同じ条件でexplicitとなる
  • (17) :
    • C++17 : 対応するコンストラクタ (3) と同じ条件でexplicitとなる
    • C++23 : 対応するコンストラクタ (3) と同じ条件で削除定義される
  • (20), (23) :
    • C++23 : それぞれ対応するコンストラクタ (6), (9) と同じ条件でexplicitとなる
    • C++23 : それぞれ対応するコンストラクタ (6), (9) と同じ条件で削除定義される
  • (21), (22) :
    • C++17 : それぞれ対応するコンストラクタ (7), (8) と同じ条件でexplicitとなる
    • C++23 : それぞれ対応するコンストラクタ (7), (8) と同じ条件で削除定義される
  • (24), (27) :
    • C++23 : それぞれ対応するコンストラクタ (10), (13) と同じ条件でexplicitとなる
    • C++23 : それぞれ対応するコンストラクタ (10), (13) と同じ条件で削除定義される
  • (25), (26) :
    • C++17 : それぞれ対応するコンストラクタ (11), (12) と同じ条件でexplicitとなる
    • C++23 : それぞれ対応するコンストラクタ (11), (12) と同じ条件で削除定義される
  • (28) :

    • C++23 : それぞれ対応するコンストラクタ (14) と同じ条件でexplicitとなる
  • C++17では、コンストラクタの各オーバーロードが条件付きでexplicitとなるよう規定された。これは、以下のような初期化子リストを使用したC++17での初期化が不適格になっていたため、適格になるようにするための変更である:

    std::tuple<int, int> pixel_coordinates()
    {
      return {10, -15};  // C++14でコンパイルエラー!
    }
    
    struct NonCopyable { NonCopyable(int); NonCopyable(const NonCopyable&) = delete; };
    std::pair<NonCopyable, double> pmd{42, 3.14};  // C++14でコンパイルエラー!
    

    • この変更はC++17に対するものであるが、コンパイラが早期に対応していたため、一部処理系ではC++14の段階から適格となっていた
  • C++23 では、ダングリング参照の作成が簡単にできていた状態を改善するべく、reference_constructs_from_temporaryが追加され、ダングリング参照が作成される場合には不適格とするようになった :

    // コンストラクタ引数で std::string が構築され
    // その一時オブジェクトが束縛されるため、ダングリング参照となっていた
    // C++23 からは不適格であり、コンパイルエラー等で未然に防がれる
    std::tuple<const std::string&, const std::string&> x("hello", "world");
    

#include <tuple>
#include <string>
#include <utility>

int main()
{
  // デフォルト構築
  std::tuple<int, char, std::string> t1;

  // コピー構築
  std::tuple<int, char, std::string> t2(t1);

  // ムーブ構築
  std::tuple<int, char, std::string> t3(std::move(t2));

  // 値を指定して構築
  std::tuple<int, char, std::string> t4(1, 'a', "hello");

  // pairから構築(2要素の場合のみ)
  std::tuple<int, char> t5 = std::make_pair(1, 'a');

  // アロケータを指定して構築。
  // std::allocator_argを第1引数にすると、第2引数がアロケータと見なされ、
  // 第3引数以降がtupleの要素となる
  std::tuple<int, char, std::string> t6(std::allocator_arg,
                                        std::allocator<std::tuple<int, char, std::string>>(),
                                        1, 'a', "hello");
}

出力

バージョン

言語

  • C++11

処理系

関連項目

参照