C++ 使用lambdas的变量模板:g+错误+;但运行与叮当声++;
在使用可变模板、类、函数和lambda时,()我发现以下代码是用C++ 使用lambdas的变量模板:g+错误+;但运行与叮当声++;,c++,templates,c++11,g++,clang++,C++,Templates,C++11,G++,Clang++,在使用可变模板、类、函数和lambda时,()我发现以下代码是用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&g
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;
}
#包括
#包括
使用名称空间std;
模板
结构重载\u集:F。。。
{
重载集(F…F):F(F)…{}
};
模板
自动过载(F…F)
{
返回过载设置(f…);
}
int main()
{
自动函数=重载(
[](int&val){val*=2;},
[](字符串&arg){arg+=arg;},
[](char&c){c='x';}
);
int-val=10;
string str=“stackoverflow”;
char ch='s';
cout这与lambda、可变模板、运算符或任何高级C++1{xy}东西几乎没有关系。让我们简化一下:
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);
}
这无法在g++
或clang++
中编译。这也是一件好事,因为这就是指定语言工作的方式
如果我们将func
更改为operator()
,g++
将继续拒绝程序,但clang++
接受或拒绝程序,具体取决于调用运算符的方式:
t.operator()(c); // rejected
t(c); // accepted
这对我来说就像一只叮当作响的虫子
为了使上述代码能够编译,需要进行一个非常小的更改:
struct test : foo, bar {
using foo::func;
using bar::func;
};
现在我不知道如何在using指令中实现包扩展,或者是否确实可行。但有一个解决方法:
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();
};
模板结构重载\u集;
模板结构重载_集{};
模板结构重载\u集:F{
使用F::operator();
重载集(F):F(F){
};
模板
结构重载集:F,重载集
{
重载集(F,Fs…Fs):F(F),重载集(Fs…{}
使用F::operator();
使用重载集::运算符();
};
通过此更改,您的代码可以同时使用g++
和clang++
@Niall进行编译:这实际上与lambdas甚至可变模板无关;即使给定从基B1
派生的最简单的struct
,B2
…使用不同的运算符()(X&)
函数,g++需要使用B1::operator();使用B2::operator();
(请参阅)。@TonyD.我认为这是一个铿锵错误-一些测试表明,铿锵从基类解析函数的方式与它解析调用运算符的方式有所不同。@Niall-gotcha,铿锵解析x()
与x.operator()()
不同。这个问题已经得到解决。OP的链接博客文章中有一个链接,这几乎就是这个解决方法。该博客提到它是一个“工业强度版本”@Niall工业版本是我见过Yakk和其他人使用的版本(基本模板、专门化的数量和完美转发的使用都有变化)