Let's take std::pair<T1, T2>
as an example. It has the following two constructors:
constexpr pair( const T1& x, const T2& y ); // #1
template< class U1, class U2 > constexpr pair( U1&& x, U2&& y ); // #2
It seems that #2 can handle all cases that #1 can handle (without worse performance), except for cases where an argument is a list-initializer. For example,
std::pair<int, int> p({0}, {0}); // ill-formed without #1
So my question is:
If #1 is only intended for list-initializer argument, since x
and y
finally bind to temporary objects initialized from list-initializers, why not use constexpr pair( T1&& x, T2&& y );
instead?
Otherwise, what's the actual intention of #1?
What if the object you want to store is a temporary one but is not movable ?
#include <type_traits>
#include <utility>
#include <iostream>
class test
{
public:
test() { std::cout << "ctor" << std::endl; }
test(const test&) { std::cout << "copy ctor" << std::endl; }
test(test&&) = delete; // { std::cout << "move ctor" << std::endl; }
~test() { std::cout << "dtor" << std::endl; }
private:
int dummy;
};
template <class T1, class T2>
class my_pair
{
public:
my_pair() {}
// Uncomment me plz !
//my_pair(const T1& x, const T2& y) : first(x), second(y) {}
template <class U1, class U2, class = typename std::enable_if<std::is_convertible<U1, T1>::value && std::is_convertible<U2, T2>::value>::type>
my_pair(U1&& x, U2&& y) : first(std::forward<U1>(x)), second(std::forward<U2>(y)) {}
public:
T1 first;
T2 second;
};
int main()
{
my_pair<int, test> tmp(5, test());
}
The above code doesn't compile because the so called "perfect" forwarding constructor of my_pair
forwards the temporary test
object as an rvalue reference which in turn tries to call the explicitly deleted move constructor of test
.
If we remove the comment from my_pair
's not so "perfect" constructor it is preferred by overload resolution and basically forces the copy of the temporary test
object and thus makes it work.
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