C++递归Variadic Lambda

Leo*_*ria 8 c++ recursion lambda templates c++14

在C++中,我们可以使用递归可变参数模板函数.例如:

template<typename ...H>
void g(){}
template<typename H, typename ...T>
void g(H h,T ...t){
    std::cout << h << "\t";
    g<T...>(t...);
}
Run Code Online (Sandbox Code Playgroud)

但是,使用lambdas似乎无法做到这一点.我的两个主要关注点是:

  • 如何建立基础案例.
  • 如何使lambda递归并且同时具有可变性.

我知道我可以有递归的lambdas但是看不到让它变成可变的方法.这种类型的功能是否仅适用于更高级别的语言,例如Javascript?

编辑:到目前为止,这是我提出的:

template<typename C,typename H, typename ...T>
std::function<void(C,H,T...)> f=[](auto&&  self,H h,T ...t){
    std::cout << h << "\t";
    if(sizeof...(t)>0)
        self(self,t...);
};
Run Code Online (Sandbox Code Playgroud)

这里的第一个参数是lambda本身.然而,主要的问题是,为了调用这个方法,我将定义类型C,我不确定如何做(或者即使它是可能的).

编辑:一种更简单的方法是:

auto f = [] (auto&&  self, auto&& h,auto&&... t) {
    std::cout << sizeof...(t) << "\n";
    if( sizeof...(t)>0 ){
        self(self,1);
    }
};

int main()
{
    f(f,1,2,3,4,5,6);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是会出现以下错误:

main.cpp:55:13: error: use of ' [with auto:1 = &; auto:2 = int; auto:3 = {}]' before deduction of 'auto'
     self(self,1);
         ^
Run Code Online (Sandbox Code Playgroud)

Cás*_*nan 6

C++ 17使用Constexpr解决了这个问题,如果:

#include <iostream>

auto f = [](auto&&... t){
    auto f_impl = [](auto& self, auto&& h, auto&&... t) {
      std::cout << sizeof...(t) << "\n";
      if constexpr ( sizeof...(t)>0 ){
        self(self,t...);
      }
    };
    return f_impl(f_impl, t...);
};

int main() {
    f(1,2,3,4,5,6);
}
Run Code Online (Sandbox Code Playgroud)

我还冒昧地将第一个参数(self)包装在"父"lambda中.

使用这个问题if(sizeof...(t))作为一个后卫的是,即使你不会调用在运行时不正确的参数的拉姆达,编译器仍需要编译表达式self(self, t...)sizeof...(t)==0,它失败.

constexpr if通过在编译时进行此检查来解决此问题,甚至在检查产生时甚至不编译块false.在C++ 17之前,条件编译语义(不包括宏)只能使用SFINAE或模板特化来实现,这两者都不能仅使用lambdas来完成.