5

首先,一个演示问题的小例子:

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’

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

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

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

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

4

2 回答 2

3

访问控制出现重载解决之后。这在标准 §13.3 中有规定

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

所以重载决议可以选择一个不适合给定上下文的函数。

于 2012-06-01T16:55:21.100 回答
-1
switch(expression)

表达式必须是整数类型或可以明确转换为整数类型的类类型。

于 2012-06-01T16:54:33.090 回答