C 递归变量lambda
C++ Recursive Variadic 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...);
}
但是,使用lambdas似乎无法完成。我的两个主要问题是:
- 如何建立基础案例。
- 如何使lambda成为递归,同时又是variadic。
我知道我可以拥有递归的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...);
};
这里的第一个论点将是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);
}
我还自由地将第一个参数(self
(包装在"父" lambda中。
使用if(sizeof...(t))
用作守护的问题是,即使您在运行时不用不正确的参数调用lambda,编译器仍然需要用sizeof...(t)==0
来编译self(self, t...)
,而CC_4失败。
constexpr if
通过在编译时进行检查来解决此问题,甚至在支票产生false
时都没有编译块。在C 17之前,只能使用SFINAE或模板专业化来实现条件汇编语义(排除宏(,这两者都不能仅使用lambdas进行。
我讨厌助手,我认为使用助手是一种误导的设计。也就是说,我在不使用小帮手的情况下找不到解决方案。
这里遇到的障碍是:
-
您不能参考其在其自己的初始化表达式中用
auto
声明的变量通过使用内部lambda将函数作为参数传递给本身来解决,以提供干净的公共接口
-
您不能将
if( sizeof... )
用作"基本案例"的守卫(或任何其他"运行时"机制(,不编译通过"超载lambda"并实际定义所有所需的功能过载(即"基本案例"也(来解决这一点
来解决的定义了lambda,您就不能"简单地"超载
这是通过使用"小"辅助代码
总的来说,一个解决方案可以就是这样:
#include <iostream>
/////////// Helper
template<class F, class... Fs>
struct overloaded : F, overloaded<Fs...>
{
using F::operator();
using overloaded<Fs...>::operator();
overloaded(F&& f, Fs&&... fs)
: F(std::move(f))
, overloaded<Fs...>(std::move(fs)...)
{}
};
template<class F>
struct overloaded<F> : F
{
using F::operator();
overloaded(F&& f)
: F(std::move(f))
{}
};
template<class... Ts>
overloaded<Ts...> overload(Ts&&...lambdas)
{ return overloaded<Ts...>{std::move(lambdas)...}; }
///////// Recursive Variadic Lambda
int main(void)
{
auto lambda = [](auto... args)
{
auto lambda_impl = overload(
[](auto self)
{
},
[] (auto self, auto first, auto...rest)
{
std::cout << first << std::endl;
self(self, rest...);
});
lambda_impl(lambda_impl, args...);
};
lambda(4, "lol", 8.3);
}
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 在 lambda 捕获中声明的变量的类型推导
- 我可以在这里替换什么,因为我不能在 C# 中使用隐式变量的 lambda 函数?
- 在 C++ 中访问 lambda 捕获初始化变量
- Visual C++: MSVC vs. GCC+CLANG: 处理 lambda 捕获类成员变量,正确的方法是什么?
- 作为模板变量的 Lambda
- 变量不在 lambda 的范围内
- 为什么 lambda 采用变量的初始值
- 为什么捕获 lambda 不捕获变量?
- C++ lambda:如何'freeze'局部变量的值?
- 获取具有静态局部变量的绑定/推断捕获 lambda 的函数指针
- Simulink "Access Violation"写入 C++ lambda 函数捕获列表中的 PWork 变量
- C++使用 lambda 初始化变量
- 如何在 lambda 表达式中传递变量?
- C++将 lambda 函数另存为成员变量,而不使用函数指针进行优化
- C++ lambda - 捕获静态成员变量
- 是否有一种方法可以编写此短片而不捕获lambda变量
- 为什么我的全球外部lambda变量在运行时不初始化
- lambda变量捕获
- 使用 auto 在 C++ 中声明 lambda 变量的首选方法是什么