7

Can someone provide a more lucid explanation of these two terms?

In other words, some simple explanation with an example, please.

(from : cppreference.com)

MoveInsertable : Specifies that a rvalue of the type can be copied in uninitialized storage.

CopyInsertable : Specifies that an instance of the type can be copy-constructed in-place, in uninitialized storage.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Ajeet Ganga
  • 8,353
  • 10
  • 56
  • 79
  • Do you know the difference between "move" and "copy" in C++11? – Drew Dormann Feb 16 '13 at 22:58
  • You're not alone with this problem; see http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-tentative.html#2177 –  Feb 16 '13 at 22:59
  • The important point is that certain types are movable but not copyable. The whole section you're referring to is just relating that idea to how allocators work. – Kerrek SB Feb 16 '13 at 23:13

1 Answers1

8

These requirements are a relationship between a type T and a container X. A container has an allocator type, A, which it uses to allocate the memory for its contained objects.

If m is one of these allocators, p a T*, rv an rvalue of type T, and v an expression of type T:

  1. CopyInsertable is defined by the standard with:

    T is CopyInsertable into X means that the following expression is well-formed:

    allocator_traits<A>::construct(m, p, v);
    
  2. MoveInsertable is defined by the standard with:

    T is MoveInsertable into X means that the following expression is well-formed:

    allocator_traits<A>::construct(m, p, rv);
    

Now to understand these definitions, we must know what allocator_traits<A>::construct does. Quite simply, in this case it calls:

m.construct(p, v) // CopyInsertable case
m.construct(p, rv) // MoveInsertable case

v and rv still have their respective value categories here because std::forward is applied to the argument of allocator_traits<A>::construct.

So what does an allocators construct member function do? Well, as you might expect, it constructs an object of type T at the location p by doing:

::new ((void*)p) T(v) // CopyInsertable case
::new ((void*)p) T(rv) // MoveInsertable case

Again, v and rv are std::forwarded.

Of course, these will invoke the copy or move constructors respectively.

So:

  1. T is CopyInsertable into X: the allocator for X can placement-new construct an element of T, passing an expression of type T
  2. T is MoveInsertable into X: the allocator for X can placement-new construct an element of T, passing an rvalue of type T
Community
  • 1
  • 1
Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • 1
    `forward` doesn't really make sense with a non-deduced type, which `T` would seem to be. – Kerrek SB Feb 16 '13 at 23:11
  • @KerrekSB I think it only looks like that because I'm enumerating the different cases. In reality, it *is* deduced. `construct` takes an `Arg&&...`, which in this case would be deduced to either `T& &&` or `T&& &&`. Edit: Ah, I realise my mistake. – Joseph Mansfield Feb 16 '13 at 23:15