Insertion to std::list<std::vector<int>> failed when using initializer list as the value?

Viewed 268

I have a C++ snippet that looks like this:

  std::list<std::vector<int>> lv;
  lv.push_back({});
  std::cout << lv.size() << std::endl; // "1"

  lv.insert(lv.end(), {});  // Oops!
  // lv.insert(lv.end(), std::vector<int>());  // OK
  std::cout << lv.size() << std::endl; // Still got "1", but why?

As you can see, when using {} to create a default std::vector<int>, the insertion didn't happen at all. While I know that there are lots of subtleties when using C++'s initializer list, I wonder what is the problem in this example?

Thanks!

2 Answers

Overload resolution for the

lv.insert(lv.end(), {});  // Oops!

call will resolve (formally, chosen as the best viable function as per [over.ics.rank]/3.1) to the following std::list<>::insert overload [extract from std::list<>::insert at cppreference, emphasis mine]:

iterator insert( const_iterator pos, std::initializer_list<T> ilist );

inserts elements from initializer list ilist before pos.

But as the initializer list is empty, there are no elements from it to be inserted.


You could likewise invoke the same insert overload with a nested list initialization within the list initialization,

lv.insert(lv.end(), {{}});  // Size is now 2.

such that the innermost list initialization will resolve to (as per [over.match.list]/1) the std::initializer_list constructor of std::vector:

vector( std::initializer_list<T> init,
        const Allocator& alloc = Allocator() );

in so inserting a single element of type std::vector<int>, specifically an an empty such vector, into the std::list<std::vector<int>> object.

When you call push_back, the {} argument is deduced to be the element type of the list, so a single vector gets inserted into the list.

When you call insert, you are using the initializer list overload, and since the initializer list is empty, no elements get added to the list.

Related