C++ 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) 你知道这里发生了什么吗?这是一个编

我正在研究一种可能被称为“重载lambda”的C++11习惯用法:

用变量模板重载n个函数似乎对我很有吸引力,但事实证明它不适用于变量捕获:任何
[&]
[=]
[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...);
}

您应该有
使用重载::运算符()和:-)@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...>;