I tried to make std::pair
with this style:
#include <iostream> struct A { A() noexcept { std::cout << "Created\n"; } A(const A&) noexcept { std::cout << "Copy\n"; } A(A&&) noexcept { std::cout << "Move\n"; } }; int main() { std::pair<A, A> a{ {},{} }; return 0; }
and got such output:
Created Created Copy Copy
instead of
Created Created Move Move
But if I define my anonymous object type (e.g. std::pair<A, A> a{A{}, A{}}
) or use std::make_pair<A, A>({}, {})
I get right result.
std::pair
constructor must use std::forward<U1>
and std::forward<U2>
to initialize objects, thus I think that my pair uses wrong constructor. Why?
std::pair is copyable only as long as whatever's in a std::pair is copyable.
1) make_pair(): This template function allows to create a value pair without writing the types explicitly.
In C++11, you can almost entirely do without make_pair. See my answer. In C++17, std::make_pair is redundant.
There's a problem with how std::pair
is defined. I'd even say it's a minor defect in the standard.
It has two constructors that could be used here:
pair(const T1 &x, const T2 &y);
, where T1
, T2
are template parameters of the pair
.
template <class U1, class U2> pair(U1 &&x, U2 &&y);
If you do std::pair<A, A> a{A{}, A{}});
, then the second constructor is selected and all is well.
But if you do std::pair<A, A> a{{}, {}};
, the compiler can't use the second constructor because it can't deduce U1
, U2
, because {}
by itself has no type. So the first constructor is used and you get a copy.
For it to work properly, std::pair
should have an extra non-template constructor pair(T1 &&, T2 &&)
, and for a good measure two extra constructors: pair(const T1 &, T2 &&)
and pair(T1 &&, const T2 &)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With