- utility[meta header]
- std[meta namespace]
- class template[meta id-type]
namespace std {
template <class T1, class T2>
struct pair;
}
pair
は、2つの異なる型の値を保持する「組」を表現するためのクラスである。また、N個の異なる型の値を保持する「タプル」を表現するためのクラスとして、tuple
クラスも提供されている。
標準ライブラリにおいてpair
は、連想配列コンテナの実装であるmap
クラスやunordered_map
クラスで、キーと値をまとめるためのデータ型として使用されている。
- C++20 :
T1
とT2
がどちらも構造的型である場合、この型は構造的型となる
名前 |
説明 |
対応バージョン |
T1 first |
1つめの要素 |
|
T2 second |
2つめの要素 |
|
名前 |
説明 |
対応バージョン |
first_type |
T1 |
|
second_type |
T2 |
|
名前 |
説明 |
対応バージョン |
swap |
2つのpair オブジェクトを入れ替える |
C++11 |
名前 |
説明 |
対応バージョン |
tuple_size |
pair の要素数を取得する(class template) |
C++11 |
tuple_element |
pair のi 番目の要素型を取得する(class template) |
C++11 |
get |
pair のi 番目の要素を参照する(function template) |
C++11 |
#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;
}
#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;
}
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