Why can't container::value_type invoke a move like make_pair can ?
I'm using Visual Studio 2012
Code example
#include <iostream>
#include <unordered_map>
#include <utility> // move, make_pair
#include <algorithm> // swap
struct move_me {
typedef move_me class_type;
int *ptr_value;
int moved;
int copied;
move_me() : ptr_value(nullptr), moved(), copied() {}
explicit move_me(const int val) : ptr_value(new int(val)), moved(), copied() {
}
~move_me() {
if (ptr_value) {
delete ptr_value;
}
}
// Copy
move_me(const move_me &other) :
moved(other.moved), copied(other.copied + 1) {
if (other.ptr_value) {
ptr_value = new int(*other.ptr_value);
} else {
ptr_value = nullptr;
}
}
move_me &operator=(const move_me &other) {
move_me(other).swap(*this);
return *this;
}
// Move
move_me(move_me &&other) {
ptr_value = other.ptr_value;
other.ptr_value = nullptr;
moved = other.moved + 1;
copied = other.copied;
}
move_me &operator=(move_me &&other) {
move_me(std::move(other)).swap(*this);
return *this;
}
void print() const {
using namespace std;
if (ptr_value)
cout << "ptr_value: " << *ptr_value << endl;
else
cout << "ptr_value: <nullptr>" << endl;
cout << "moved: " << moved << endl;
cout << "copied: " << copied << endl;
}
void swap(move_me& other) {
std::swap(ptr_value, other.ptr_value);
std::swap(moved, other.moved);
std::swap(copied, other.copied);
}
size_t hash() const {
return std::hash<int>()(*ptr_value);
}
bool operator==(const class_type& other) const { return *ptr_value == *other.ptr_value; }
bool operator< (const class_type& other) const { return *ptr_value < *other.ptr_value; }
bool operator<=(const class_type& other) const { return *ptr_value <= *other.ptr_value; }
};
struct hash_move_me {
size_t operator()(const move_me& key_val) const {
return key_val.hash();
}
};
int main()
{
using namespace std;
typedef unordered_map<move_me, size_t, hash_move_me> m_type;
m_type m;
auto find_and_prt = [&](const int val) {
m.find(move_me(val))->first.print();
cout << endl;
};
// Normal way
// Expect only moves
m.insert(m_type::value_type(move_me(111), 123));
find_and_prt(111);
// Lets make it very clear for the compiler that we want a move here
m.insert(move(m_type::value_type(move(move_me(222)), 123)));
find_and_prt(222);
// We're in luck, special case, standard container
m.insert(make_pair(move_me(333), 123));
find_and_prt(333);
cout << "done" << endl << endl;
return 0;
}
Add your 2¢