First, a tiny example that demonstrates the problem:
struct Bar {
enum Baz {aa, bb, cc};
Baz baz_;
operator Baz() const { return baz_; }
private:
template<typename T> operator T() const;
};
int main() {
Bar bar;
switch (bar) {
case Bar::aa:
break;
case Bar::bb:
break;
case Bar::cc:
break;
default:
break;
}
return 0;
}
Compiling this code with g++ 4.7.0 gives the following error:
foo.cpp: In function ‘int main()’:
foo.cpp:12:16: error: ambiguous default type conversion from ‘Bar’
foo.cpp:12:16: error: candidate conversions include ‘template<class T> Bar::operator T() const’
My understanding is that, since the struct object is being “switched” on, the compiler will try to find a conversion function to an integral or enum type. I explicitly provide a public conversion function to the Bar::Baz enum type and would like it to use that.
The confusing part to me is that the compiler also finds the private conversion function and then cannot decide which to use. Why is it even considering the private function? If I add an explicit cast, say switch((int)bar), then only the private conversion function matches and the compiler rightly complains that it cannot use it since it’s private. So, since the private conversion function can’t be used in this context, why isn’t the choice between the two unambiguous?
Interestingly, I believe (though I’m not 100% sure) this code compiles without error on g++ 4.6.
edit: As pointed out by James McNellis in the comments, the fact that the private conversion function is templated is also relevant here.
Access control comes after overload resolution. This is specified in the standard, §13.3
So the overload resolution can chose a function that is not appropriate for the given context.