6

Possible Duplicate:
initializer_list and move semantics

In this code:

#include <vector>
#include <initializer_list>

template<typename T>
class some_custom_container : public std::vector<T>
{
public:
   some_custom_container(const std::initializer_list<T>& contents)
   {
      for (auto& i : contents)
        this->emplace_back(std::move(i));
   }
};

class test_class
{};

int main()
{
    test_class a;

    some_custom_container<test_class> i = { a, test_class(), a };
}

If I've understand it, all objects in { a, test_class(), a } are safe-constructed: the named-objects are copied and the unnamed objects are moved to construct the initializer_list. After, this initializer_list is passed by reference to the some_custom_container's constructor.

Then, to avoid useless doble-copies I move all of them to fill the vector.

Is it safe this constructor? I mean, in a strange situation, for example if T is evaluated as a reference & or &&, is the vector always well-filled (contains it safe objects)?

If this is the case, why the initializer_list constructor implementations of stl containers aren't implemented in this way? As I know, their constructors copy and don't move the contents.

Community
  • 1
  • 1
ABu
  • 10,423
  • 6
  • 52
  • 103
  • It does not even compile because initializer lists only provide const access to their contents and you cannot move from references to const. See also: http://stackoverflow.com/questions/8468774/can-i-list-initialize-a-vector-of-move-only-type – R. Martinho Fernandes Dec 19 '12 at 17:19
  • 2
    That won't prevent it from compiling, only moving. The copy constructor would be called. – Puppy Dec 19 '12 at 19:01

1 Answers1

5

initializer_list only provides const access to its elements. You could use const_cast to make that code compile, but then the moves might end up with undefined behaviour (if the elements of the initializer_list are truly const). So, no it is not safe to do this moving. There are workarounds for this, if you truly need it.

Community
  • 1
  • 1
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • Consider the in idiom described on cpptruths (http://cpptruths.blogspot.com/2013/09/21-ways-of-passing-parameters-plus-one.html). The idea is to determine lvalue/rvalue at run-time and then call move or copy-construction. in will detect rvalue/lvalue even though the standard interface provided by initializer_list is const reference. – Sumant Sep 24 '13 at 19:53
  • @Sumant Does that humungous mess actually provide any measurable benefits to performance or memory usage, and if so, a sufficiently large amount of such benefits to adequately offset how terrible it looks and the fact that it takes about an hour to figure out what it's trying to do? I kinda doubt it. – underscore_d Aug 09 '16 at 20:02