I really don't understand this, I thought that compiler first executes what is in braces and then gives the result to the most appropriate function. Here it looks like it gives the function an initializer list to deal with it...
#include <string>
#include <vector>
using namespace std;
void func(vector<string> v) { }
void func(vector<wstring> v) { }
int main() {
func({"apple", "banana"});
}
error:
<stdin>: In function 'int main()':
<stdin>:11:27: error: call of overloaded 'func(<brace-enclosed initializer list>)' is ambiguous
<stdin>:11:27: note: candidates are:
<stdin>:6:6: note: void func(std::vector<std::basic_string<char> >)
<stdin>:8:6: note: void func(std::vector<std::basic_string<wchar_t> >)
Why isn't my func(vector<string> v)
overload called, and can I make it so?
This one was subtle.
std::vector
has a constructor taking two range iterators. It is a template constructor (defined in 23.6.6.2 of the C++11 Standard):Now the constuctor of
std::vector<wstring>
accepting aninitializer_list
is not a match for the implicit conversion in your function call, (const char*
andstring
are different types); but the one above, which is of course included both instd::vector<string>
and instd::vector<wstring>
, is a potentially perfect match, becauseInputIterator
can be deduced to beconst char*
. Unless some SFINAE technique is used to check whether the deduced template argument does indeed satisfy theInputIterator
concept for the vector's underlying type, which is not our case, this constructor is viable.But then again, both
std::vector<string>
andstd::vector<wstring>
have a viable constructor which realizes the conversion from the braced initializer list: hence, the ambiguity.So the problem is in the fact that although
"apple"
and"banana"
are not really iterators(*), they end up being seen as such. Adding one argument"joe"
to the function call fixes the problem by disambiguating the call, because that forces the compiler to rule out the range-based constructors and choose the only viable conversion (initializer_list<wstring>
is not viable becauseconst char*
cannot be converted towstring
).*Actually, they are pointers to
const char
, so they could even be seen as constant iterators for characters, but definitely not for strings, as our template constructor is willing to think.