【发布时间】:2016-01-23 01:57:17
【问题描述】:
又是一轮clang vs gcc的时间了。 Live example on godbolt.org.
测试0:重载的可调用对象
struct Trad
{
auto operator()(int) { return 1; }
auto operator()(float) { return 2; }
auto operator()(double) { return 3; }
};
int main()
{
assert(Trad{}(1) == 1);
assert(Trad{}(1.f) == 2);
assert(Trad{}(1.0) == 3);
}
- g++ 5.2 编译并运行。
- clang++ 3.5 (和更高版本) 编译并运行。
测试 1:重载的可调用对象,通过 lambda 继承生成
template <typename... TFs>
struct overload_set : TFs...
{
overload_set(TFs... fs) : TFs(fs)... {}
};
template <typename... TFs>
auto overload(TFs&&... fs)
{
return overload_set<TFs...>{fs...};
}
int main()
{
auto func = overload
(
[](int) { return 1; },
[](float) { return 2; },
[](double) { return 3; }
);
assert(func(1) == 1);
assert(func(1.f) == 2);
assert(func(1.0) == 3);
}
-
g++ 5.2 无法编译。
错误:对成员“operator()”的请求不明确
clang++ 3.5 (和更高版本) 编译并运行。
这里什么编译器是正确的?
【问题讨论】:
-
MSVS2015 将编译第二个示例,但智能感知不喜欢它。
-
这是骗人的……某事。无论如何,GCC 是对的。
-
@T.C:为什么 GCC 是对的? ...
make_overload生成的代码不应该等同于struct Trad { ... }吗?是否有任何解决方法可以使make_overload工作? -
@VittorioRomeo 尝试
struct Trad0 { auto operator()(int){return 1;}};等,然后尝试struct Trad:Trad0, Trad1, Trad2 {等。请注意,当您在此 版本的Trad上调用operator()时,会出现同样的歧义。基本上,当在不同的基提供的方法之间选择重载时,重载规则不会按照您希望的方式工作,其中没有发生using将它们移动到相同的范围:相反,您会得到“模棱两可”。 -
@t.c.我以前在这里看到过这个。我不记得哪一个是正确的,只是为了让它始终如一地工作,你必须跳过某些环节。
标签: c++ gcc lambda clang c++14