[英]Variadic template using lambdas : error with g++ but running with clang++
While playing with variadic templates, classes, functions and lambdas, ( from here ) I found that following code is running with clang++
while not running with g++
: 在使用可变参数模板,类,函数和lambdas时( 从这里 )我发现以下代码在运行时使用
clang++
而不是使用g++
运行:
#include <iostream>
#include <string>
using namespace std;
template <class... F>
struct overload_set : F...
{
overload_set(F... f) : F(f)... {}
};
template <class... F>
auto overload(F... f)
{
return overload_set<F...>(f...);
}
int main()
{
auto func = overload (
[](int &val) { val *= 2; },
[](string &arg) { arg += arg; },
[](char &c) { c = 'x'; }
);
int val = 10;
string str = "stackoverflow";
char ch = 's';
cout << val << " : " << str << " : " << ch << endl;
func(val);
func(str);
func(ch);
cout << val << " : " << str << " : " << ch << endl;
return 0;
}
For clang
: coliru 对于
clang
: coliru
For g++
: coliru 对于
g++
: coliru
g++
is giving ambiguous operator()
for func(val)
, func(str)
and func(c)
. g++
为func(val)
, func(str)
和func(c)
赋予了模糊的operator()
func(c)
。 I think the operator()
must not be ambiguous, as each one is having different arguments. 我认为
operator()
不能含糊不清,因为每个都有不同的参数。
What's the problem with g++
? g++
什么问题?
This has little to do with lambdas, variadic templates, operators or any advanced C++1{xy} stuff. 这与lambdas,可变参数模板,运算符或任何高级C ++ 1 {xy}东西几乎没有关系。 Let's simplify:
让我们简化一下:
struct foo
{
void func(int&){}
};
struct bar
{
void func(char&){}
};
struct test : foo, bar {};
int main()
{
test t;
int i = 1;
char c = 'a';
t.func(i);
t.func(c);
}
This fails to compile in either g++
or clang++
. 这无法在
g++
或clang++
。 Which is a good thing too, because that's how the language is specified to work. 这也是一件好事,因为这是指定语言的工作方式。
If we change func
to operator()
, g++
continues to reject the program but clang++
either accepts or rejects it, depending on how the operator is called: 如果我们将
func
更改为operator()
, g++
继续拒绝该程序,但clang++
接受或拒绝它,具体取决于调用运算符的方式:
t.operator()(c); // rejected
t(c); // accepted
Which looks like a clang bug to me. 这对我来说就像一个铿锵的虫子。
In order to make the code above compile, a very small change is needed: 为了使上面的代码编译,需要进行非常小的更改:
struct test : foo, bar {
using foo::func;
using bar::func;
};
Now I have no idea how to make pack expansion work in the using directive, or if it's indeed possible. 现在我不知道如何在using指令中进行包扩展工作,或者它确实可行。 But there's a workaround:
但有一个解决方法:
template <class... F> struct overload_set;
template <> struct overload_set<> {};
template <class F> struct overload_set<F> : F {
using F::operator();
overload_set(F f) : F(f) {}
};
template <class F, class... Fs>
struct overload_set<F, Fs...> : F, overload_set<Fs...>
{
overload_set(F f, Fs... fs) : F(f), overload_set<Fs...>(fs...) {}
using F::operator();
using overload_set<Fs...>::operator();
};
With this change your code compiles with both g++
and clang++
. 通过此更改,您的代码将使用
g++
和clang++
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.