I am using emplace_back
to add items to an std::deque
. During its construction, the new item may add other items to the std::deque
it is being constructed into. This leads to very interesting behavior. Consider this snippet:
#include <iostream>
#include <deque>
#include <string>
struct foo
{
std::string m_marker;
foo(std::deque<foo>& into, const std::string& marker, bool createInner = true)
: m_marker(marker)
{
if (createInner)
{
std::cout << "Marker is " << m_marker << std::endl;
into.emplace_back(into, "my other marker", false);
std::cout << "Marker is now " << m_marker << std::endl;
}
}
};
int main()
{
std::deque<foo> foos;
foos.emplace_back(foos, "my initial marker");
std::cout << "There are " << foos.size() << " items in the deque:" << std::endl;
for (foo& f : foos)
{
std::cout << f.m_marker << std::endl;
}
}
It creates a deque
of foo
objects. The first object's marker is "my initial marker"
, and since createInner
is true
, it's going to create a second one. I would expect the following result:
Marker is my initial marker
Marker is now my initial marker
There are 2 items in the deque:
my initial marker
my other marker
However, with clang++ (tags/Apple/clang-421.11.66) and libc++ (not sure what version it is), this is what I get:
Marker is my initial marker
Marker is now my other marker
There are 2 items in the deque:
my other marker
As you can see, the m_marker
field of the first object was overwritten by the second one, and the second one to show up in the deque is now empty. So obviously there's a bug somewhere, and it has to be either that it is undefined behavior to modify a deque
during a call to emplace_back
, or that libc++ is not doing its job. Which one is it?