Tech Off Post

Single Post Permalink

View Thread: A moving question
  • User profile image
    Norville​Shaggy

    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;
    }