pair(); // (1) C++03
constexpr pair(); // (1) C++11
EXPLICIT constexpr pair(); // (1) C++17
explicit(see below) constexpr pair(); // (1) C++20
pair(const pair&) = default; // (2)
pair(pair&&) = default; // (3) C++11
pair(const T1& x, const T2& y); // (4) C++03
constexpr pair(const T1& x, const T2& y); // (4) C++14
EXPLICIT constexpr pair(const T1& x, const T2& y); // (4) C++17
explicit(see below) constexpr pair(const T1& x, const T2& y); // (4) C++20
template <class U, class V>
pair(U&& x, V&& y); // (5) C++11
template <class U, class V>
constexpr pair(U&& x, V&& y); // (5) C++14
template <class U, class V>
EXPLICIT constexpr pair(U&& x, V&& y); // (5) C++17
template <class U, class V>
explicit(see below) constexpr pair(U&& x, V&& y); // (5) C++20
template <class U = T1, class V = T2>
explicit(see below) constexpr pair(U&& x, V&& y); // (5) C++23
template<class U, class V>
explicit(see below) constexpr pair(pair<U, V>& p); // (6) C++23
template <class U, class V>
pair(const pair<U, V>& p); // (7) C++03
template <class U, class V>
constexpr pair(const pair<U, V>& p); // (7) C++14
template <class U, class V>
EXPLICIT constexpr pair(const pair<U, V>& p); // (7) C++17
template <class U, class V>
explicit(see below) constexpr pair(const pair<U, V>& p); // (7) C++20
template <class U, class V>
pair(pair<U, V>&& p); // (8) C++11
template <class U, class V>
constexpr pair(pair<U, V>&& p); // (8) C++14
template <class U, class V>
EXPLICIT constexpr pair(pair<U, V>&& p); // (8) C++17
template <class U, class V>
explicit(see below) constexpr pair(pair<U, V>&& p); // (8) C++20
template<class U, class V>
explicit(see below) constexpr pair(const pair<U, V>&& p); // (9) C++23
template<pair-like P>
explicit(see below) constexpr pair(P&& p); // (10) C++23
template <class... Args1, class... Args2>
pair(piecewise_construct_t,
tuple<Args1...> first_args,
tuple<Args2...> second_args); // (11) C++11
template <class... Args1, class... Args2>
constexpr pair(piecewise_construct_t,
tuple<Args1...> first_args,
tuple<Args2...> second_args); // (11) C++20
概要
pair
オブジェクトを構築する。
- (1) : デフォルトコンストラクタ(
first
とsecond
を初期化して構築) - (2) : コピーコンストラクタ
- (3) : ムーブコンストラクタ
- (4) :
first
とsecond
の変換可能な型の値から構築 - (5) :
first
とsecond
に変換可能な型の値からムーブ構築 - (6) : 変換可能な他の
pair
オブジェクトから構築 - (7) : 変換可能な他の
pair
オブジェクトから構築 - (8) : 変換可能な他の
pair
オブジェクトからムーブ構築 - (9) : 変換可能な他の
pair
オブジェクトから構築 - (10) :
pair-like
なオブジェクトから構築 - (11) :
first
とsecond
のコンストラクタ引数をstd::tuple
に詰めて受け取り、first_args
とsecond_args
内のそれぞれの要素を転送してfirst
とsecond
を直接構築- 転送は、
std::tuple
オブジェクト(first_args
/second_args
)内の要素x
とその型U
(Args1...
/Args2...
に含まれる型)によって、std::forward<U>(x)
のようにしてコンストラクタに渡される
- 転送は、
テンプレートパラメータ制約
- (1) :
first_type
とsecond_type
がどちらもis_default_constructible<T>::value == true
であること
- (4) :
first_type
とsecond_type
がどちらもis_copy_constructible<T>::value == true
であること
- (5) :
is_constructible<first_type, U&&>::value && is_constructible<second_type, V&&>::value
であること- C++14まで :
U
がfirst_type
に暗黙変換可能でない場合、もしくはV
がsecond_type
に暗黙変換可能でない場合、この関数はオーバーロード解決から除外される
- (6)-(10) :
- C++23 :
FWD(u)
をstatic_cast<deccltype(u)>(u)
と定義して、is_constructible_v<first_type, decltype(get<0>(FWD(p)))> && is_constructible_v<second_type, decltype(get<1>(FWD(p)))>
であること
- C++23 :
- (7) :
is_constructible<first_type, const U&>::value && is_constructible<second_type, const V&>::value
であること- C++14まで :
const U&
がfirst_type
に暗黙変換可能でない場合、もしくはconst V&
がsecond_type
に暗黙変換可能でない場合、この関数はオーバーロード解決から除外される - C++23 : (6)-(10) での定義参照
- (8) :
is_constructible<first_type, U&&>::value && is_constructible<second_type, V&&>::value
であること- C++14まで :
U
がfirst_type
に暗黙変換可能でない場合、もしくはV
がsecond_type
に暗黙変換可能でない場合、この関数はオーバーロード解決から除外される - C++23 : (6)-(10) での定義参照
- (11) :
is_constructible<first_type, Args1&&...>::value && is_constructible<second_type, Args2&&...>::value
であること
delete定義される条件(C++23)
- (5) :
reference_constructs_from_temporary_v<first_type, U1&&> || reference_constructs_from_temporary_v<second_type, U2&&>
である場合、このコンストラクタは削除定義される - (6)-(10) :
FWD(u)
をstatic_cast<deccltype(u)>(u)
と定義してreference_constructs_from_temporary_v<first_type, decltype(get<0>(FWD(p)))> || reference_constructs_from_temporary_v<second_type, decltype(get<1>(FWD(p)))>
である場合、このコンストラクタは削除定義される
- (11) : 要素型(
T1, T2
のどちらかもしくは両方)が参照型であり、初期化によって一時オブジェクトを束縛することになる場合、このコンストラクタは削除定義される- 上記のコンストラクタと同様に、
reference_constructs_from_temporary
を使用して判定される
- 上記のコンストラクタと同様に、
explicitになる条件
- (1) :
- C++17 :
first_type
とsecond_type
のどちらかが非暗黙にデフォルト構築できない場合、explicit
指定される
- C++17 :
- (4) :
- C++17 :
!is_convertible_v<const first_type&, first_type> || !is_convertible_v<const second_type&, second_type>
である場合、explicit
指定される
- C++17 :
- (5) :
- C++17 :
!is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
である場合、explicit
指定される
- C++17 :
- (6)-(10) :
FWD(u)
をstatic_cast<deccltype(u)>(u)
と定義して- C++23 :
!is_convertible_v<decltype(get<0>(FWD(p))), first_type> || !is_convertible_v<decltype(get<1>(FWD(p))), second_type>
である場合、explicit
指定される
- (7) :
- C++17 :
!is_convertible_v<const U1&, first_type> || !is_convertible_v<const U2&, second_type>
である場合、explicit
指定される - C++23 : (6)-(10) での定義参照(複雑であるが、条件は同等である)
- C++17 :
- (8) :
- C++17 :
!is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
である場合、explicit
指定される - C++23 : (6)-(10) での定義参照(複雑であるが、条件は同等である)
- C++17 :
備考
-
(11)のコンストラクタでは
first
/second
をそのコンストラクタ引数から直接構築するため、コピーもムーブもできないような型でも初期化することができる -
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::pair<const std::string&, const std::string&> x("hello", "world");
例
#include <iostream>
#include <utility>
#include <string>
#include <tuple> // std::make_tuple
template <class T1, class T2>
void print(const std::string& name, const std::pair<T1, T2>& p)
{
std::cout << name << " : (" << p.first << "," << p.second << ")" << std::endl;
}
struct X {
int a, b, c;
X() : a(0), b(0), c(0) {}
X(int a, int b, int c) : a(a), b(b), c(c) {}
};
std::ostream& operator<<(std::ostream& os, const X& x)
{
return os << "X(" << x.a << " " << x.b << " " << x.c << ")";
}
struct Y {
int a, b;
Y() : a(0), b(0) {}
Y(int a, int b) : a(a), b(b) {}
};
std::ostream& operator<<(std::ostream& os, const Y& y)
{
return os << "Y(" << y.a << " " << y.b << ")";
}
int main()
{
// (1) デフォルト構築
{
constexpr std::pair<int, double> p1;
print("p1", p1);
}
// (2) コピー構築
{
std::pair<int, std::string> p(1, "abc");
std::pair<int, std::string> p2 = p;
print("p2", p2);
}
// (3) ムーブ構築
{
std::pair<int, std::string> p(1, "abc");
std::pair<int, std::string> p3 = std::move(p);
print("p3", p3);
}
// (4) firstとsecondの初期値から構築
{
std::pair<int, std::string> p4(1, std::string("abc"));
print("p4", p4);
}
// (5) firstとsecondの右辺値からムーブ構築
{
int x = 1;
std::string s = "abc";
std::pair<int, std::string> p5(std::move(x), std::move(s));
print("p5", p5);
}
// (7) 変換可能なpairから構築
{
std::pair<int, const char*> p(1, "abc");
std::pair<int, std::string> p6 = p;
print("p6", p6);
}
// (8) 変換可能なpairからムーブ構築
{
std::pair<int, const char*> p(1, "abc");
std::pair<int, std::string> p7 = std::move(p);
print("p7", p7);
}
// (11) first_typeとsecond_typeのコンストラクタ引数から構築
{
std::pair<X, Y> p8(std::piecewise_construct,
std::make_tuple(1, 2, 3),
std::make_tuple(4, 5));
print("p8", p8);
}
}
出力
p1 : (0,0)
p2 : (1,abc)
p3 : (1,abc)
p4 : (1,abc)
p5 : (1,abc)
p6 : (1,abc)
p7 : (1,abc)
p8 : (X(1 2 3),Y(4 5))
バージョン
言語
- C++11 : ムーブ構築とpiecewise構築
処理系
- Clang: ??
- GCC: 4.6.1 ✅
- ICC: ??
- Visual C++: 2010 ✅, 2012 ✅, 2013 ✅, 2015 ✅
- C++03で規定されていたものは、2010より前のバージョンから実装されている。
- 2010までは、(11)
std::piecewise_construct
版が実装されていない。 - 2013までは、デフォルトコンストラクタに
constexpr
が付与されていない。
関連項目
参照
- N2345 Placement Insert for Containers (Revision 2)
- (11)の最初の提案
- N3471 Constexpr Library Additions: utilities, v3
- N4387 Improving Pair and Tuple (Revision 3)
- C++17での条件付き
explicit
の導入
- C++17での条件付き
- P1032R1 Misc constexpr bits
- P0892R2
explicit(bool)
- C++20での
explicit(bool)
構文への対応
- C++20での
- P1951R1 Default Arguments for
pair
's Forwarding Constructor- C++23での
{}
完全転送への対応
- C++23での
- P2165R4 Compatibility between
tuple
,pair
and tuple-like objectspair-like
なオブジェクトからの構築
- P2255R2 A type trait to detect reference binding to temporary
- 参照型を要素に持つ場合にダングリング参照が容易に作成できていたのを不適格にする
- P2321R2
zip