Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Private conversion function results in "ambiguous default type conversion" error (c++)

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.

like image 946
Drew Frank Avatar asked Nov 03 '22 22:11

Drew Frank


1 Answers

Access control comes after overload resolution. This is specified in the standard, §13.3

Overload resolution is a mechanism for selecting the best function to call given a list of expressions that are to be the arguments of the call and a set of candidate functions that can be called based on the context of the call. The selection criteria for the best function are the number of arguments, how well the arguments match the types of the parameters of the candidate function, how well (for nonstatic member functions) the object matches the implied object parameter, and certain other properties of the candidate function. [Note: the function selected by overload resolution is not guaranteed to be appropriate for the context. Other restrictions, such as the accessibility of the function, can make its use in the calling context ill-formed. ]

So the overload resolution can chose a function that is not appropriate for the given context.

like image 174
juanchopanza Avatar answered Nov 09 '22 14:11

juanchopanza