void foo(std::pair<int, std::vector<std::unique_ptr<int>>>&&) {}
foo({{}, {}});
The above does not compile with an error message reporting that it attempts to call into the copy constructor of std::vector<std::unique_ptr<int>>
(which is deleted). However, the following works
void foo(std::vector<std::unique_ptr<int>>&&) {}
void foo(const std::vector<std::unique_ptr<int>>&) {}
foo({});
What rules am I missing that make the second example work and the first example not work?
It seems I have an answer to my own question -- this does not work because the nested list initialization overload only has the following std::pair
constructor to match
pair( const T1& x, const T2& y );
The other std::pair
constructor with two arguments is templated without a default type, so it does not get considered
template< class U1, class U2 >
pair( U1&& x, U2&& y );
If we were to change this to a type where the second constructor has default types or has non-templated rvalue overloads, then the above works
template <typename T1, typename T2>
class Pair {
public:
Pair(const T1&, const T2&) {}
Pair(T1&&, T2&&) {}
};
void foo(Pair<int, std::vector<std::unique_ptr<int>>>&&) {}
foo({{}, {}});
https://wandbox.org/permlink/pbmme350X7XjM8cI
Or
template <typename T1, typename T2>
class Pair {
public:
Pair(const T1&, const T2&) {}
template <typename U1 = T1, typename U2 = T2>
Pair(U1&&, U2&&) {}
};
void foo(Pair<int, std::vector<std::unique_ptr<int>>>&&) {}
foo({{}, {}});