[英]Generic lambdas, overloading, std::is_invocable and SFINAE - different behavior among GCC and Clang
[英]Overloading structs with template call operator and generic lambdas - gcc vs clang
我发现了一个代码片段,它在clang ++ 4(和trunk)中编译并正常工作,但无法在g ++ 7(和trunk)中编译。 假设我有以下struct
类型:
struct a { void foo() { } };
struct b { void bar() { } };
struct c { void bar() { } };
我想创建一个过载设定的lambda表达式出它处理a
明确的,而b
和c
都“中招”使用的通用拉姆达auto
参数:
auto ol = overload([](a x) { x.foo(); },
[](auto x){ x.bar(); })
当我调用ol(a{})
:
clang ++编译并按预期运行: a
匹配第一个lambda,而b
和c
匹配第二个lambda。
g ++无法编译,出现以下错误:
error: 'struct a' has no member named 'bar' [](auto x){ x.bar(); }; ~~^~~
似乎编译器试图实例化第二个lambda,即使第一个lambda是更好的匹配方式。 希望这是一个bug,因为它对我来说似乎不直观。
请注意,如果使用一些老式的struct
实例而不是lambda表达式,两个编译器都能正常工作:
struct s0
{
auto operator()(a x) const { x.foo(); }
};
struct s1
{
template <typename T>
auto operator()(T x) const { x.bar(); }
};
auto os = overload(s0{}, s1{});
os(a{}); // OK!
我希望lambda大致相当于s0
和s1
,所以这更令人惊讶。
这是我生成重载集的方式:
template <typename... Fs>
struct overloader : Fs...
{
template <typename... FFwds>
overloader(FFwds&&... fs) : Fs{std::forward<FFwds>(fs)}...
{
}
using Fs::operator()...;
};
template <typename... Fs>
auto overload(Fs&&... fs)
{
return overloader<std::decay_t<Fs>...>{std::forward<Fs>(fs)...};
}
这是gcc.godbolt.org
上的一个实例 ,展示了编译器之间的不同行为。
这是一个g ++错误吗? 或者标准中有什么东西使lambda在这种情况下的行为与struct
实例不同?
我认为这是一个gcc bug(提交为80767 ),与[temp.inst] / 9运行冲突:
实现不应隐式实例化函数模板,变量模板,成员模板,非虚拟成员函数,成员类,类模板的静态数据成员或constexpr if语句的子语句,除非这样的实例化是必须的。
使用auto = a
的通用lambda operator()
的实例化不是必需的,因此不应该实例化它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.