Why can't GCC disambiguate multiple inherited functions (yet clang can)? [duplicate]

感情迁移 提交于 2020-01-22 13:43:25

问题


Possible Duplicate:
Why do multiple-inherited functions with same name but different signatures not get treated as overloaded functions?

This fails to compile in the indicated place with 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 does compile this code, which makes me uncertain if the code is really valid C++ or not. I was about to conclude optimistically that clang was right and g++ was wrong, but then I made a small change which made clang have a similar error:

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
}

The only change I made there was to use a named function f rather than operator(). I don't see why this should even matter, but it does: this version does not compile with g++ nor with clang.


回答1:


I think it has something to do with hiding the function(s) in the base classes, and the GCC's error message doesn't seem to help much, even if you use struct instead of enum : In fact, the error message is misleading, because now Ea and Eb are two different classes, with no implicit conversion from Ea to Eb, the ambiguity shouldn't arise, but GCC seems to disagree with me : http://ideone.com/cvzLW (see the modification also).

Anyway, if you bring the functions in the class scope, explicitly by writing using as:

struct Sbroken : Sa, Sb 
{
   using Sa::operator();
   using Sb::operator();
};

then it works : http://ideone.com/LBZgC

Same with other example as well:

struct Sbroken : Sa, Sb 
{
   using Sa::f;
   using Sb::f;
};

Code : http://ideone.com/3hojd




回答2:


Trying to understand the actual text in the standard (§10.2) isn't easy, but there is an example which makes it clear: name lookup for a name x in the derived class fails if the name isn't present in the derived class, but it is present in more than one base class, and it isn't hidden. (Hidden isn't relevant here, as it only intervenes when virtual inheritance is present.) As far as I can tell, this is the case regardless of the name of the member; I can find no exception if the member happens to have the special name operator(). Overload resolution doesn't come into play, because their is failure in the name lookup, before the overload set is completely built. I'm pretty sure that both snippets of code are illegal, and that there is a bug in clang.

You can use using declarations to inject the names into the derived class, or you can explicitly define forwarding operators in the derived class. Once the name is found in the derived class, the compiler stops, and does not look in the base classes.



来源:https://stackoverflow.com/questions/8083546/why-cant-gcc-disambiguate-multiple-inherited-functions-yet-clang-can

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!