Search code examples
c++constructorcopy-constructorstd-pairmove-constructor

std::allocator_traits::construct invokes wrong constructor


Motivated from Haskell, I tried to implement std::forward_list like this:

namespace std {
    template <class T, class Allocator = allocator<T>>
    class forward_list {
        typename allocator_traits<Allocator>::template rebind_alloc<pair<forward_list<T>,T>> alloc;
        typename allocator_traits<decltype(alloc)>::pointer ptr;
    public:
        // ...
        void push_front(const T &value) {
            auto newPtr = allocator_traits<decltype(alloc)>::allocate(alloc, 1);
            allocator_traits<decltype(alloc)>::construct(alloc, newPtr, move(*this), value);
            ptr = newPtr;
        }
        // ...
    };
}

But the construct in push_front calls copy constructor, rather than move constructor.

I don't understand. construct has forwarding references as arguments, so does the constructor of std::pair. So the rvalue reference from std::move should be delivered intact. So why is this happening?

(I'm sorry if this is a dupe. The searching system of Stack Exchange doesn't cut it.)


Solution

  • It turns out I implemented the move constructor wrongly:

    forward_list(
        forward_list &&other
    ) : forward_list(other, other.alloc) {}
    

    It must be:

    forward_list(
        forward_list &&other
    ) : forward_list(move(other), other.alloc) {}