Yes, using explicit liberally is the better way to go.
MSVC incorrectly matching overload's.
I can reproduce the issue with VS2010 such that it appears to be a compiler bug. Would be interested to know if it's fixed in 2012 or 2013 or whether there's something horrendously obscure about C++ overload resolution rules when it comes to ellipsis that actually make this the correct (albeit unexpected) behaviour.
For me, I have two issues with the compiler's behaviour...
Issue 1: Complaining about 2 overloads but only listing one of them in the error. Normally it lists all the options.
This can be reproduced as follows:
struct FromStr
{
FromStr(const char *) {}
};
void f(const char *, ...) {}
void f(FromStr, const char *) {}
int main()
{
f("hello", 0);
}
Gives the error:
error C2666: 'f' : 2 overloads have similar conversions
could be 'void f(FromStr,const char *)'
while trying to match the argument list '(const char [6], int)'
Normally it gives the word "or" and lists the other possibilities.
Issue 2: If you introduce a similar 3rd overload, one that should not be a candidate for overload resolution, the error will bizarrely say that now this is the ambiguous signature:
struct FromStr
{
FromStr(const char *) {}
};
struct FromNothing {};
void f(const char *, ...) {}
void f(FromStr, const char *) {}
void f(FromNothing, const char *) {}
int main()
{
f("hello", 0);
}
Gives the error:
error C2666: 'f' : 2 overloads have similar conversions
could be 'void f(FromNothing,const char *)'
while trying to match the argument list '(const char [6], int)'
Which just seems completely bogus to me.
Consequently, I think you do have a signature ambiguity but not the one listed in the error message. Rather, it'll be these two signatures:
QWVector2i DrawTextf(QWBaseMesh *Mesh, const QWVector2i &Position, const char *Text, ...);
QWVector2i DrawTextf(QWBaseMesh *Mesh, const QWVector2i &Position, const QWVector4 &DefaultColor, const char *Text, ...);
... because in both cases the 3rd argument can accept the string literal (but the first signature would win that resolution because it's an exact match) whilst the 4th argument can accept a literal 0 (but the second signature would win that resolution because it'll prefer the fixed argument rather than the ellipsis), so it's an ambiguous tie.
In this case, I think marking the constructors as explicit is the right way to go.
Would be interested to know if it's fixed in 2012 or 2013 or whether there's something horrendously obscure about C++ overload resolution rules when it comes to ellipsis that actually make this the correct (albeit unexpected) behaviour.
I have Visual Studio 2013 Ultimate Update 2.
Issue 1
1><..>\source.cpp(11): error C2666: 'f' : 2 overloads have similar conversions
1> <..>\source.cpp(7): could be 'void f(FromStr,const char *)'
1> <..>\source.cpp(6): or 'void f(const char *,...)'
1> while trying to match the argument list '(const char [6], int)'
Issue 2
1><..>\source.cpp(14): error C2666: 'f' : 2 overloads have similar conversions
1> <..>\source.cpp(10): could be 'void f(FromNothing,const char *)'
1> <..>\source.cpp(9): or 'void f(FromStr,const char *)'
1> <..>\source.cpp(8): or 'void f(const char *,...)'
1> while trying to match the argument list '(const char [6], int)'