在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,但是看不到使它可变的方法。这种功能是否仅在更高级的语言(例如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 ++ 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] 删除。
我来说两句