Difference between MoveInsertable and CopyInsertable? suggests that a type T
is MoveInsertable if the allocator can construct an object of type T
from an rvalue of the same type. However, MoveConstructible also requires T
to be constructible from an rvalue of the same type. Then, what's the difference between them?
Asked
Active
Viewed 231 times
3

cpplearner
- 13,776
- 2
- 47
- 72
1 Answers
5
There's no meaningful difference in the case of default allocator (std::allocator<T>
). For unspecialized std::allocator<T>
, one can treat MoveInsertable as a synonym for move-constructible.
However, the difference manifests if an allocator has member construct
, and that member does different thing from the default allocator_traits<A>::construct
. A typical example is std::pmr::polymorphic_allocator
, which performs the so-called "uses-allocator construction":
- if
std::uses_allocator_v<T, polymorphic_allocator<T>>
is false, the behavior is same asallocator_traits<A>::construct
; - if
std::uses_allocator_v<T, polymorphic_allocator<T>>
is true, the allocator is passed as additional argument to the constructor.
Therefore, one can invent a type that is MoveInsertable with polymorphic allocator, but not MoveConstructible, or vice versa. (More realistically, one can create a type whose move-insertion has different effect from move-construction.)
#include <memory>
#include <memory_resource>
#include <vector>
struct evil {
using allocator_type =
std::pmr::polymorphic_allocator<evil>; // make std::uses_allocator return true
evil();
evil(evil&&) = delete; // not move constructible
evil(evil&&, const allocator_type&);
};
int main() {
evil a;
evil b = std::move(a); // Error: evil is not MoveConstructible
std::pmr::vector<evil> v;
v.push_back(std::move(a)); // OK, evil is MoveInsertable
}

cpplearner
- 13,776
- 2
- 47
- 72