【发布时间】:2011-12-26 09:08:12
【问题描述】:
使用 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 编译。
【问题讨论】:
-
你能看一下
clang生成的代码,看看它是否做了什么有意义的事情吗? -
Comeau 的编译器(非常符合标准)在您的第一个 sn-p 上也会失败并出现歧义错误。
-
答案:来自N3242: 13.3.1.1.2 类类型对象的调用[over.call.object]/1"
T的函数调用操作符通过普通查找得到在(E).operator()的上下文中名称为operator()。”因此Sbroken()(Ea0)被解释为Sbroken().operator(Ea0)。其行为与普通成员函数的行为相同,在“可能重复”问题中进行了描述。
标签: c++ operator-overloading multiple-inheritance overloading ambiguous