C++ C++;11“;超载λ“;使用可变模板和可变捕获
我正在研究一种可能被称为“重载lambda”的C++11习惯用法:C++ C++;11“;超载λ“;使用可变模板和可变捕获,c++,c++11,lambda,variadic-templates,template-meta-programming,c++17,C++,C++11,Lambda,Variadic Templates,Template Meta Programming,C++17,我正在研究一种可能被称为“重载lambda”的C++11习惯用法: 用变量模板重载n个函数似乎对我很有吸引力,但事实证明它不适用于变量捕获:任何[&][=][y][&y](如果是在成员函数中,则为[this]等)都会导致编译失败:错误:调用“(重载)(char*&)不匹配“(使用我的本地GCC 4.9.1和ideone.com GCC 5.1) 另一方面,固定的2元案例没有遇到这个问题。(在ideone.com上尝试将第一个#if 0更改为#if 1) 你知道这里发生了什么吗?这是一个编
[&]
[=]
[y]
[&y]
(如果是在成员函数中,则为[this]
等)都会导致编译失败:错误:调用“(重载)(char*&)不匹配“
(使用我的本地GCC 4.9.1和ideone.com GCC 5.1)
另一方面,固定的2元案例没有遇到这个问题。(在ideone.com上尝试将第一个#if 0
更改为#if 1
)
你知道这里发生了什么吗?这是一个编译器错误,还是我偏离了C++11/14规范
#包括
使用名称空间std;
#如果0
模板
结构重载:F1,F2{
重载(F1,F2):F1(F1),F2(F2){}
使用F1::operator();
使用F2::运算符();
};
模板
自动使_过载(F1、F2){
返回过载(f1、f2);
}
#否则
模板
结构过载;
模板
结构重载:F0,重载{
重载(F0-F0,Frest…rest):F0(F0),重载(rest…{}
使用F0::operator();
};
模板
结构重载{
重载(){}
};
模板
自动使_过载(Fs…Fs){
返回过载(fs…);
}
#恩迪夫
#如果0
#定义CAP
#定义PRINTY()
#否则
#定义CAP y
#define PRINTY()cout重载解析仅适用于公共作用域中存在的函数。这意味着第二个实现无法找到第二个重载,因为您没有将函数调用运算符从重载导入重载
但是,非捕获lambda类型定义了一个转换运算符,该运算符与lambda的函数调用运算符具有相同的签名。此转换运算符可以通过名称查找找到,这是在删除捕获部件时调用的
对于捕获和非捕获lambda都有效,并且总是调用操作符()
而不是转换操作符的正确实现,应该如下所示:
template <class... Fs>
struct overload;
template <class F0, class... Frest>
struct overload<F0, Frest...> : F0, overload<Frest...>
{
overload(F0 f0, Frest... rest) : F0(f0), overload<Frest...>(rest...) {}
using F0::operator();
using overload<Frest...>::operator();
};
template <class F0>
struct overload<F0> : F0
{
overload(F0 f0) : F0(f0) {}
using F0::operator();
};
template <class... Fs>
auto make_overload(Fs... fs)
{
return overload<Fs...>(fs...);
}
您应该有使用重载::运算符()第二个实现中的code>和:-)@PiotrSkotnicki很有趣,但是使用重载::操作符()添加了代码>没有改善这种情况。啊,你是对的,我没有仔细阅读联机编译器的错误消息。。。缺少使用重载::运算符()的代码>是关键。我还必须将基本情况定义为一元:模板结构重载:F0{重载(F0 F0):F0(F0){}使用F0::operator();}代码>我接受您的意见作为解决方案!“一个非捕获lambda定义了一个转换操作符”我不知道,如果你想在一个重载集中有很多重载(比如说,超过100个),你需要将线性继承改为一个大致平衡的二进制继承。你会想重新考虑你的设计,因为为什么你一次重载超过100个lambda?(此外,二进制版本的代码更多)
template <class... Fs>
struct overload;
template <class F0, class... Frest>
struct overload<F0, Frest...> : F0, overload<Frest...>
{
overload(F0 f0, Frest... rest) : F0(f0), overload<Frest...>(rest...) {}
using F0::operator();
using overload<Frest...>::operator();
};
template <class F0>
struct overload<F0> : F0
{
overload(F0 f0) : F0(f0) {}
using F0::operator();
};
template <class... Fs>
auto make_overload(Fs... fs)
{
return overload<Fs...>(fs...);
}
template <typename... Ts>
struct overload : Ts... { using Ts::operator()...; };
template <typename... Ts>
overload(Ts...) -> overload<Ts...>;