2

std::initializer_list<T> allocates a temporary array T[] whose elements are copied from with the list-initializer. It's begin and end methods return const T*. This makes it so that you can't move the elements and you perform yet another copy. However, it's trivial to do

Vector(std::initializer_list<T> IL) :Size{IL.size()}, :Storage{new T[size]} {
    T* slot = Storage;
    for (auto ele = IL.begin(); ele != IL.end(); ele++, slot++)
        *slot = std::move(*const_cast<T*>(ele));
}

I'm sure there's some valid reason why std::initializer_list<T>::begin returns a const T* and thus you shouldn't do what's shown above but I don't see it.

lanza
  • 1,512
  • 2
  • 13
  • 26
  • Does this answer your question? [initializer\_list and move semantics](https://stackoverflow.com/questions/8193102/initializer-list-and-move-semantics) – Evg Dec 06 '19 at 07:06

1 Answers1

4

The initializer list doesn't just return T const*. The array that backs it is declared const too.

[dcl.init.list]

5 An object of type std​::​initializer_­list<E> is constructed from an initializer list as if the implementation generated and materialized a prvalue of type “array of N const E”, where N is the number of elements in the initializer list.

This means your trivial example potentially attempts to modify an object that's declared const. That results in undefined behavior. In the interest of avoiding UB, we shouldn't do that.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458