C ++递归可变参数Lambda

莱昂纳多·法里亚

在C ++中,我们可以具有递归可变参数模板函数。例如:

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

但是,使用lambda似乎无法做到这一点。我的两个主要问题是:

  • 如何建立基础案例。
  • 如何使lambda递归并同时可变参数。

我知道我可以使用递归lambda,但是看不到使它可变的方法。这种功能是否仅在更高级的语言(例如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...);
};

在这里,第一个参数是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;
}

但是给出以下错误:

main.cpp:55:13: error: use of ' [with auto:1 = &; auto:2 = int; auto:3 = {}]' before deduction of 'auto'
     self(self,1);
         ^
卡西奥·雷南(CássioRenan)

如果满足以下条件,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);
}

我还自由地将第一个parameter(self包装在“父” lambda中。

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

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章