Can you guess the output of this trivial program?
#include <vector>
#include <string>
#include <exception>
#include <iostream>
int main()
{
try {
struct X {
explicit X(int) {}
X(std::string) {} // Just to confuse you more...
};
std::vector<X>{"a", "b"};
} catch (std::exception& x) {
std::cerr << x.what();
}
}
Well, I couldn't, which cost me a day of "research", before landing here, with finally having it distilled from some complex real-life code (with type aliases everywhere, anon. unions with non-POD members & hand-orchestrated ctors/dtors etc., just for the vibe).
And... I still can't see what's going on! Can someone please give a gentle hint? (Hopefully just a blind spot. I no longer do C++ professionally.)
Note: clean compile* with both (latest) MSVC /W4 and GCC -Wall; same output in both (semantically).
* Even without the "confuse-the-reader" line. Which I think I'm gonna have nightmares from.
(Please bear with me for trying not to spoiler it by spelling everything out even more — after all, this truly is self-explanatory as-is, right? Except, the exact opposite for me...)
This creates a vector from two iterators of type
const char*using the constructor that takes two iterators:It's just bad luck that the decay of the two
const char[]s becomes perfect iterators that fulfills the LegacyInputIterator requirement.The iterators do not point to an array/contiguous area and the program therefore has undefined behavior.
What happens under the hood is most likely that it'll try to get from the first
const char*to the second and run out of bounds as soon as its passing the null terminator after the'a'.A similar construction that would actually work: