无法使用g ++ 4.6.1在指定位置编译:
enum Ea { Ea0 };
enum Eb { Eb0 };
struct Sa { void operator()(Ea) {} };
struct Sb { void operator()(Eb) {} };
struct Sbroken : Sa, Sb {};
struct Sworks {
void operator()(Ea) {}
void operator()(Eb) {}
};
int main() {
Sworks()(Ea0);
Sbroken()(Ea0); // g++ can't disambiguate Ea vs. Eb
}
Clang 2.8确实编译了这段代码,这让我不确定代码是否真的有效C ++。我乐观地总结说clang是对的,g ++是错的,但后来我做了一个小小的改动,让clang有类似的错误:
enum Ea { Ea0 };
enum Eb { Eb0 };
struct Sa { void f(Ea) {} };
struct Sb { void f(Eb) {} };
struct Sbroken : Sa, Sb {};
struct Sworks {
void f(Ea) {}
void f(Eb) {}
};
int main() {
Sworks().f(Ea0);
Sbroken().f(Ea0); // both clang and g++ say this is ambiguous
}
我在那里做的唯一改变是使用命名函数f
而不是operator()
。我不明白为什么这应该重要,但确实如此:这个版本不用g ++和clang编译。
答案 0 :(得分:5)
我认为它与隐藏基类中的函数有关,即使你使用struct
而不是{{1},GCC的错误信息也似乎没什么帮助。 }:实际上,错误消息具有误导性,因为现在enum
和Ea
是两个不同的类,无隐式转换从Eb
到{{1不应该出现歧义,但GCC似乎不同意我:http://ideone.com/cvzLW(也参见修改)。
无论如何,如果你把这些函数带到了类范围,那么显式地将Ea
写成:
Eb
然后它起作用:http://ideone.com/LBZgC
与其他例子相同:
using
答案 1 :(得分:4)
试图理解标准(第10.2节)中的实际文本并不容易,
但是有一个例子可以说清楚:名称x
的名称查找
如果派生类中不存在名称,则派生类中的类失败
class,但它存在于多个基类中,而不是
隐。 (隐藏在这里不相关,因为它只在虚拟时进行干预
继承存在。)据我所知,情况就是这样
无论会员的名字如何;我发现如果没有例外
成员恰好有特殊名称operator()
。超载
决议没有发挥作用,因为他们的名字是失败的
查找,在完全构建过载集之前。我相当确定
这两段代码都是非法的,而且还有一个bug
铛。
您可以使用using
声明将名称注入派生名称
class,或者您可以在派生中明确定义转发运算符
类。一旦在派生类中找到名称,编译器就会停止,
并且不会查看基类。