Michael Walz Michael Walz - 2 months ago 16
C++ Question

Overloading, variadic functions and bool type

Following program compiles fine and works as expected. Its output is:


1

2


#include <stdio.h>

class Foo
{
public:
void Bar(const char* b, ...) { printf("1\n"); };
void Bar(int a, const char* b, ...) { printf("2\n"); };
};

int main()
{
Foo foo1;
foo1.Bar("Test", "xx", 1, 2);
foo1.Bar(1, "xx", "xx", 2, 2);
}


Now if I change the
int
parameter of the second
Bar
function into
bool
and
foo1.Bar(1, "xx", "xx", 2, 2);
into
foo1.Bar(true, "xx", "xx", 2, 2);
, then the following line won't compile and I get the error:
'Foo::Bar': 2 overloads have similar conversions
:

foo1.Bar("Test", "xx", 1, 2);


The whole program that doesn't compile:

#include <stdio.h>

class Foo
{
public:
void Bar(const char* b, ...) { printf("1\n"); };
void Bar(bool a, const char* b, ...) { printf("2\n"); };
};

int main()
{
Foo foo1;
foo1.Bar("Test", "xx", 1, 2); // error: 'Foo::Bar': 2 overloads have similar conversions
foo1.Bar(true, "xx", "xx", 2, 2);
}


I don't understand why there is an ambiguity in the second case.

EDIT

But if pointers implicitly convert to
bool
, why does following compile ?

#include <stdio.h>

class Foo
{
public:
void Bar(const char* b) { printf("1\n"); };
void Bar(bool a) { printf("2\n"); };
};

int main()
{
Foo foo1;
foo1.Bar("Test");
foo1.Bar(true);
}

Answer

When you match "Test", "xx", 1, 2 against const char*, ..., the conversion sequence for the first argument has exact match rank, the second through fourth one are ellipsis conversion sequences. So (exact match, ellipsis, ellipsis, ellipsis).

When you match "Test", "xx", 1, 2 against bool, const char*, ..., the first conversion sequence for the first argument has conversion rank; the second is an exact match, the third and fourth are ellipsis conversion sequences. In other words, (conversion, exact match, ellipsis, ellipsis).

Exact match beats conversion; everything beats ellipsis (see [over.ics.rank]). Thus we have a so-called criss-cross situation here where one function has a better conversion sequence for one argument and the other function has a better conversion sequence for another argument. Since a necessary (but not sufficient) condition for a function to be better than another function is that none of the conversion sequences are worse than those of the other function ([over.match.best]/1), neither of those two functions is better than the other.