Overloaded lambdas in C++ and differences between clang and gcc

女生的网名这么多〃 提交于 2019-11-27 01:34:03

Looks like a Clang bug to me.

The general rule is that member functions of the same name in different base classes do not overload. For example:

struct Foo { void bar(); };
struct Baz { void bar(int); };
struct Quux : Foo, Baz { };

int main() { Quux().bar(); } // error on both GCC and Clang

For whatever reason, Clang fails to diagnose this ambiguity for operator().

A using-declaration lifts the named base class members to the derived class scope, allowing them to overload. Hence:

struct Quux_2 : Foo, Baz { using Foo::bar; using Baz::bar; };
Quux_2().bar(); // OK.

In the working version of the code, the using declarations recursively bring every operator() declaration in the template arguments into the scope of the most derived class, allowing them to overload.

The original code shouldn't compile, gcc is correct here. See [class.member.lookup]:

Otherwise (i.e., C does not contain a declaration of f or the resulting declaration set is empty), S(f,C) is initially empty. If C has base classes, calculate the lookup set for f in each direct base class subobject Bi, and merge each such lookup set S(f,Bi) in turn into S(f,C).
— [..]
— Otherwise, if the declaration sets of S(f,Bi) and S(f,C) differ, the merge is ambiguous...

The initial declaration set is empty (overload has no methods) - so merge all the bases, all of whom have differing sets. So the merge should fail. That rule only applies if the declaration set of overload is empty though, which is why the explicit adding of the using F1::operator() works.

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