user3514538 user3514538 - 7 days ago 5
C++ Question

Why does a constructor which takes iterators require elements to be EmplaceConstructible?

I have seen requirements for a sequence stl containers in the Standard (n4296), 23.2.3/4 (Table 100) and have read that a constructor which takes arguments-iterators (X - container, i and j - input iterators)

X(i, j)
X a(i, j)


requires a container's element type to be EmplaceConstructible.

Requires: T shall be EmplaceConstructible into X from *i


I think that a constructor can be implemented through calling std::allocator_traits::construct (m, p, *it) method for each iterator in range (where m - allocator of type A, p - pointer to memory, it - iterator in [i; j), and there is only CopyInsertable concept for elements is required because only one argument is provided for copying/moving, whereas EmplaceConstructible concept requires element to be constructed from a set of arguments. Is there any reasons for that decision?

Answer

CopyInsertable is a binary concept - given a container X it applies to a single type T, which is required to have a copy constructor. However, *i is allowed to be a different type from T, as long as there is a way to (implicitly) construct T from *i:

  char s[] = "hello world!";
  std::vector<int> v(std::begin(s), std::end(s));
  // int is EmplaceConstructible from char

A (contrived) example where T is not CopyInsertable:

struct nocopy {
  nocopy(int) {}
  nocopy(nocopy const&) = delete;
  nocopy(nocopy&&) = delete;
};
int a[]{1, 2, 3};
std::vector<nocopy> v(std::begin(a), std::end(a));