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

履歴 編集

class template
<utility>

std::pair

namespace std {
  template <class T1, class T2>
  struct pair;
}

概要

pairは、2つの異なる型の値を保持する「組」を表現するためのクラスである。また、N個の異なる型の値を保持する「タプル」を表現するためのクラスとして、tupleクラスも提供されている。

標準ライブラリにおいてpairは、連想配列コンテナの実装であるmapクラスやunordered_mapクラスで、キーと値をまとめるためのデータ型として使用されている。

  • C++20 : T1T2がどちらも構造的型である場合、この型は構造的型となる

メンバ変数

名前 説明 対応バージョン
T1 first 1つめの要素
T2 second 2つめの要素

メンバ関数

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

メンバ型

名前 説明 対応バージョン
first_type T1
second_type T2

非メンバ関数

比較演算子

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

入れ替え

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

ヘルパ関数

名前 説明 対応バージョン
make_pair pairを構築するヘルパ関数

タプルインタフェース

名前 説明 対応バージョン
tuple_size pairの要素数を取得する(class template) C++11
tuple_element pairi番目の要素型を取得する(class template) C++11
get pairi番目の要素を参照する(function template) C++11

推論補助

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

特殊化

名前 説明 対応バージョン
common_type 異なるpair間の共通型を取得できるようにする特殊化 C++23
basic_common_reference 異なるpair間の共通の参照型を取得出来るようにする特殊化 C++23

基本的な使い方 (C++03)

#include <iostream>
#include <utility>
#include <string>

int main()
{
  // pairオブジェクトの構築
  std::pair<int, std::string> p = std::make_pair(1, "hello");

  // 要素の参照
  std::cout << p.first << std::endl;
  std::cout << p.second << std::endl;
}

出力

1
hello

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

#include <iostream>
#include <utility>
#include <string>

// 関数から2つの値を返す
std::pair<int, std::string> f()
{
  // std::make_pair()はほとんどの状況で必要ない
  return {1, "hello"};
}

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

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

出力

1
hello

プロキシ参照としての使い方(C++23)

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

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

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

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

    std::pair<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()
{
    // プロキシ参照である pair の性質
    {
        A a{0, 0.0};

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

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

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

        // const std::pair<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);

        // プロキシ参照として使える pair 同士の 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

関連項目

参照