最終更新日時: 2026年04月09日 08時44分02秒 (JST)
Akira Takahashi が更新

履歴 編集

class template
<tuple>

# std::tuple(C++11)

    namespace std {
      template <class... Args>
      class tuple;
    }

## 概要

`tuple`型は、複数の型の値を保持する「タプル」を表現するためのクラスである。

`pair`型は2つの型の値を保持する「組」を表現することができるが、`tuple`ではN個の型の値を扱うことができる。

## メンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`(constructor)` | コンストラクタ | C++11
`operator=` | 代入演算子 | C++11
`swap` | 異なる`tuple`オブジェクトと値を入れ替える | C++11

## 非メンバ関数

### タプル生成関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`ignore` | 無視する要素のプレースホルダー(constant variable) | C++11
`make_tuple` | 引数のコピーからタプルを生成する | C++11
`forward_as_tuple` | 引数の完全な型からタプルを生成する | C++11
`tie` | 引数への参照からタプルを生成する | C++11
`tuple_cat` | 複数のタプルから1つのタプルを生成する | C++11

### 要素アクセス

名前 | 説明 | 対応バージョン
--- | --- | ---
`get` | `tuple`の`i`番目の要素を参照する | C++11

### 入れ替え

名前 | 説明 | 対応バージョン
--- | --- | ---
`swap` | 2つの`tuple`オブジェクトを入れ替える | C++11

### 比較演算子

名前 | 説明 | 対応バージョン
--- | --- | ---
`operator==` | 等値比較を行う | C++11
`operator!=` | 非等値比較を行う | C++11
`operator<=>` | 三方比較を行う | C++20
`operator<` | 左辺が右辺よりも小さいか比較を行う | C++11
`operator<=` | 左辺が右辺以下か比較を行う | C++11
`operator>` | 左辺が右辺より大きいか比較を行う | C++11
`operator>=` | 左辺が右辺以上か比較を行う | C++11

## 推論補助

名前 | 説明 | 対応バージョン
--- | --- | ---
`(deduction_guide)` | クラステンプレートの推論補助 | C++17

## tuple-like とのユーティリティ

名前 | 説明 | 対応バージョン
--- | --- | ---
`operator==` | `tuple-like`なオブジェクトとの等値比較を行う | C++23
`operator<=>` | `tuple-like`なオブジェクトとの三方比較を行う | C++23
`common_type` | `tuple-like`なオブジェクトとの共通型を取得できるようにする特殊化 | C++23
`basic_common_reference` | `tuple-like`なオブジェクトとの共通の参照型を取得出来るようにする特殊化 | C++23

## 例

### 基本的な使い方 (C++11)

    #include <iostream>
    #include <tuple>
    #include <string>

    int main()
    {
      // 3要素のタプルを作る
      std::tuple<int, char, std::string> t = std::make_tuple(1, 'a', "hello");

      // 0番目の要素を参照
      int& i = std::get<0>(t);
      std::cout << i << std::endl;

      // 2番目の要素を参照
      std::string& s = std::get<2>(t);
      std::cout << s << std::endl;
    }

#### 出力

    1
    hello

### 基本的な使い方 (C++17)

    #include <iostream>
    #include <tuple>
    #include <string>

    // 関数から複数の値を返す
    std::tuple<int, char, std::string> f()
    {
      // std::make_tuple()はほとんどの状況で必要ない
      return {1, 'a', "hello"};
    }

    int main()
    {
      // 構造化束縛でタプルを分解して、それぞれの要素を代入
      auto [a, b, c] = f();

      std::cout << a << std::endl;
      std::cout << b << std::endl;
      std::cout << c << std::endl;
    }

#### 出力

    1
    a
    hello

### プロキシ参照としての使い方（C++23）

C++23 で`zip_view`などが追加されたことに伴い、すべての要素がプロキシ参照であるような`tuple`はプロキシ参照として使用することが出来るようになった。

    #include <iostream>
    #include <tuple>
    #include <string_view>
    #include <format>
    #include <utility>

    struct A
    {
        A(int i, double d)
            : i(i)
            , d(d)
        {}

        std::tuple<int&, double&> f()
        {
            // this が A* なので
            // i: int
            // d: double
            // ということと同じ
            return {i, d};
        }

        std::tuple<const int&, const double&> f() const
        {
            // this が const A* なので
            // i: const int
            // d: const double
            // ということと同じ
            return {i, d};
        }

    private:
        int    i;
        double d;
    };

    int main()
    {
        // プロキシ参照である tuple の性質
        {
            A a{0, 0.0};

            // std::tuple<int&, double&>
            /***/ auto /***/ proxy = a.f();

            // const std::tuple<int&, double&>
            const auto const_proxy = a.f();

            // std::tuple<const int&, const double&>
            /***/ auto /***/ proxy_to_const = std::as_const(a).f();

            // const std::tuple<const int&, const double&>
            const auto const_proxy_to_const = std::as_const(a).f();

            // OK（各要素が指すオブジェクトの値について、代入操作がなされる）
            proxy       = a.f();
            const_proxy = a.f();

            // NG（各要素が指すオブジェクトを変更できない！）
            // proxy_to_const       = a.f();
            // const_proxy_to_const = a.f();
        }

        // 使い方
        {
            auto print = [](std::string_view prefix, A& a) {

                // 構造化束縛で分解
                // i: int&
                // d: double&
                auto [i, d] = a.f();

                std::cout << std::format("{}: i={}, d={}\n", prefix, i, d);
            };

            A a{0, 0.0}, b{1, 1.0};

            print("before a", a);
            print("before b", b);

            // プロキシ参照として使える tuple 同士の swap 操作で
            // 問題なく各要素が指す先のオブジェクトについて swap 操作が行える
            std::ranges::swap(a.f(), b.f());

            print("after  a", a);
            print("after  b", b);
        }
    }

#### 出力

    before a: i=0, d=0
    before b: i=1, d=1
    after  a: i=1, d=1
    after  b: i=0, d=0

## バージョン

### 言語

- C++11

### 処理系

- Clang: 3.0 ✅
- GCC: 4.3.4 ✅, 4.4.4 ✅, 4.5.2 ✅, 4.6.1 ✅
- ICC: ?
- Visual C++: 2008 ✅, 2010 ✅

## 関連項目

- `std::pair`
- C++17 構造化束縛
- C++26 コンパイル時のタプルやリストを展開処理する`template for`文

## 参照

- タプル - Wikipedia
- P2321R2 `zip`