that is what I expect when I pass a pair (compound) value of an int and a string to a function that wants a vector of strings.
Well, there's your problem.
{...}
is not a "compound value". It is not a list. It says, "initialize an object using these values". If the object in question is an aggregate, it will use aggregate initialization. If the object in question is a non-aggregate type, it will pick a constructor to call, based on the matching constructors of the type and the various rules for braced-init-lists in C++11.
You shouldn't think of {10, "foo"}
as a list of two values. It is an initializer that contains two values. It could be used with a std::pair<int, const char *>
, and so forth.
The reason why std::vector
's constructor isn't explicit is precisely to allow this construct. The single-argument constructor is explicit because otherwise, implicit conversion rules would allow this:
std::vector<T> v = 5; //???
Or, more importantly:
void Foo(const std::vector<T> &v);
Foo(5); //???
We don't want integers to be implicitly convertible to std::vector
s. However, when you're using an initializer, it's more reasonable to allow a wider range of "implicit" conversions, because you can see the {}
syntax there.
With the single-argument case, it isn't clear what the user means. With the {} syntax, it is clear what the user means: to initialize the object.
Foo({10, "foo"}); //Initializes the first argument given the values.