私有转换函数导致“模糊的默认类型转换”错误(c ++)

时间:2012-06-01 16:49:06

标签: c++ g++ type-conversion

首先,一个证明问题的小例子:

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;
}

使用g ++ 4.7.0编译此代码会出现以下错误:

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’

我的理解是,由于结构对象被“切换”,编译器将尝试找到转换函数为整数或枚举类型。我明确地向Bar :: Baz枚举类型提供了一个公共转换函数,并希望它能够使用它。

令我感到困惑的是,编译器还会找到私有转换函数,然后无法决定使用哪个。为什么甚至考虑私人功能?如果我添加一个显式的强制转换,比如switch((int)bar),那么只有私有转换函数匹配,并且编译器正确地抱怨它不能使用它,因为它是私有的。那么,由于私有转换函数不能在这种情况下使用,为什么两者之间没有明确的选择呢?

有趣的是,我相信(虽然我不是100%肯定)这个代码在g ++ 4.6上编译时没有错误。

编辑正如James McNellis在评论中所指出的那样,私有转换函数的模板化也与此相关。

2 个答案:

答案 0 :(得分:3)

在重载解析后访问控制。这在标准§13.3

中规定
  

重载解析是一种机制,用于在给定表达式列表的情况下选择要调用的最佳函数   作为调用的参数和一组可以根据的上下文调用的候选函数   呼叫。最佳函数的选择标准是参数的数量,参数的好坏程度   匹配候选函数的参数类型,如何(对于非静态成员函数)   object匹配隐含的对象参数以及候选函数的某些其他属性。 [注意:   由重载决策选择的函数不保证适合上下文。其他   限制(例如函数的可访问性)可以使其在调用上下文中的使用不正确。 ]

因此,重载决策可以选择一个不适合给定上下文的函数。

答案 1 :(得分:-1)

switch(expression)

表达式必须是整数类型或类型,并且有明确的转换为整数类型。