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...)
vector<X>{"a", "b", "c"};
to understand the problem. Change it tovector<X>{X{"a"}, X{"b"}};
to fix the problem. – Putman"a"
and one from"b"
. I can't figure out what else you would be expecting to happen? – SpectaclesX
s string constructor isn't removed. Why would you think it's removed? – Spectaclesvector
constructor. – Globuliferousstd::string
by value Demo though ;-) – Boobexplicit
keyword mumbling "not my job"... – Happystl
tag was there for a reason actually, because this isn't just a simplevector
issue: it comes from the interop. of iterators, ranges and containers in general. I just happened to use avector
. The extra tags are welcome, thx. – Happystl
tag refers to the Standard Template Library, a very influential library that formed the ideological basis (and no small amount of the initial implementations) of the C++ Standard Library back in 1998. Odds are that you are not using the STL today, so removing the tag is justified.std
would be more appropriate, but probably still too broad since this is about std library containers. Not sure if there's a tag for that, though. – Globuliferousvector<X> v = {"a", "b"};
works correctly. It only breaks without=
. – Scutcheonrollback
for your edit)? Because addingstd::
for such a short, simple example, where clarity and brevity is paramount, is mere OCD, and lowers the readability of the question for no benefits. For the title, I'm open to some changes (albeit I'm planning to add a summary answer, where Google will be able to easily find everything), but that must be a separate change. – Happystd::vector
causing the issue. The changes improved the clarity. Previously there was "action at a distance" fromusing namespace std;
(FWIW, removing theusing namespace
also made the code shorter) – Aileyvector<X> v = {"a", "b"};
would still call the same constructor. Tryvector<X> v = {"a", "b", "c"};
and it won't compile – Flitastd::vector<X> v{"ab", "b"};
and compile with optimization. It still has undefined behavior, but will most likely create oneX
(using theint
constructor) from'a'
. The reason is that the compiler most likely will just store"ab\0"
in memory so the string literal"b"
is just a pointer to"ab" + 1
. – Flita