I'm trying to insert a move-only type into a map. I have the following piece of code:
#include <map>
class Moveable
{
public:
Moveable() = default;
Moveable(const Moveable&) = delete;
Moveable(Moveable&&) = default;
Moveable& operator=(const Moveable&) = delete;
Moveable& operator=(Moveable&&) = default;
};
int main() {
std::map<int,Moveable> my_map;
Moveable my_moveable_1, my_moveable_2, my_moveable_3;
my_map.insert(std::pair<int,Moveable>{1, std::move(my_moveable_1)}); // (1)
my_map.insert(std::make_pair(2, std::move(my_moveable_2))); // (2)
my_map.insert({3, std::move(my_moveable_3)}); // (3)
return 0;
}
What happens is that using VisualC++ lines 1,2 and 3 compile. In clang and gcc, only 1 and 2 compile and line 3 gives an error (use of deleted copy constructor).
Question: Which compiler is right and why?
Try it here: rextester
std::map::insert
has (among others) the following overloads:
// 1.
std::pair<iterator,bool> insert( const value_type& value );
// 2. (since C++11)
template< class P >
std::pair<iterator,bool> insert( P&& value );
// 3. (since C++17)
std::pair<iterator,bool> insert( value_type&& value );
The first overload obviously cannot be used with move-only types. But the second overload, while available in C++11, does not work with braces here because template argument deduction does not occur with braces (at least in C++11, not sure about later standards).
Both your first and second call to insert
work in C++11 or later because the compiler knows the type, but the third fails.
C++17 adds another overload that works with braces and move-only types. Now as for why it works with certain compilers and not others, this is most likely due to diffences in the level of C++17 support, or compiler flags.
UPDATE: Just to make it painfully obvious: With using braces I mean using braces only (aggregate initialization or implicit constructor call), ie insert({k,v})
, not insert(pair<K,V>{k,v})
. In the latter case, the type is known and the templated overload can be selected even in C++11.
I've tested your code with with g++ 7.3 and it compiles without error!
With clang++ 5.0.1 it doesn't compile.
I think that you are using a feature of the c++20 so the support is not yet ready on all compilers.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.