Codes below doesnt' works properly, when I reference to it, it causes Member call on null pointer error, if it's not supported, why it allow the use of insert(end, {})(No compile error).
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<vector<pair<int, int>>> vv;
auto it = vv.insert(vv.end(), {});
cout << it->size() << endl;
}
When I changed {} to vector<pair<int, int>>, no error shows and print 0.
Solved by comments, It calls iterator insert( const_iterator pos, std::initializer_list<T> ilist ), So change it to insert(end, {{}}) could work.
According to cppreference – std::vector<T,Allocator>::insert(), all flavors of insert() return the iterator of first inserted element or the insertion position if nothing was inserted.
In OPs exposed MCVE:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<vector<pair<int, int>>> vv;
auto it = vv.insert(vv.end(), {});
cout << it->size() << endl;
}
the line
auto it = vv.insert(vv.end(), {});
doesn't use the
iterator insert( const_iterator pos, const T& value );
as it might be expected but the
iterator insert( const_iterator pos, std::initializer_list<T> ilist );.
Hence, there are 0 elements inserted and the insert() returns the end() iterator which was passed.
So,
cout << it->size() << endl;
accesses the contents of end() which is Undefined Behavior.
I made a small sample to demonstrate this:
#include <initializer_list>
#include <iostream>
#include <vector>
template <typename T>
struct Container: std::vector<T> {
using typename std::vector<T>::iterator;
using typename std::vector<T>::const_iterator;
iterator insert( const_iterator pos, const T& value )
{
std::cout << "insert single value\n";
return std::vector<T>::insert(pos, value);
}
iterator insert( const_iterator pos, std::initializer_list<T> ilist )
{
std::cout << "insert initializer list\n";
return std::vector<T>::insert(pos, ilist);
}
};
using namespace std;
int main() {
Container<vector<pair<int, int>>> vv;
auto it = vv.insert(vv.end(), {});
cout << /*it->*/vv.size() << endl;
}
Output:
insert initializer list
0
Live Demo on coliru
Note:
I'm aware that it's, at least, bad style to overload std::vector.
I did this exceptionally to show the used function call (and I didn't have a better idea how to achieve this).
The line auto it = vv.insert(vv.end(), {}); is using the form iterator insert( const_iterator pos, std::initializer_list<T> ilist );.
As int the line auto it = vv.insert(vv.end(), {});, the initlizer list have no element so no element is inserted in the vector vv.
As there is no element is inserted so it is same as vv.end() for which it is invalid to deference.
You can verify it via checking the length of vv after insertion. See sample code here to check it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With