C++;将捕获作为函数指针的lambda 我玩的是C++ LAMBDAS,它们的隐式转换为函数指针。我的起始示例是使用它们作为ftw函数的回调。这正如预期的那样有效 #include <ftw.h> #include <iostream> using namespace std; int main() { auto callback = [](const char *fpath, const struct stat *sb, int typeflag) -> int { cout << fpath << endl; return 0; }; int ret = ftw("/etc", callback, 1); return ret; } #包括 #包括 使用名称空间std; int main() { 自动回调=[](常量字符*fpath,常量结构stat*sb, int-typeflag)->int{ cout
由于捕获lambda需要保留一个状态,因此实际上没有简单的“解决方法”,因为它们不仅仅是普通函数。函数指针的意义在于它指向一个单一的全局函数,而这些信息没有空间容纳状态 最接近的解决方法(本质上放弃状态性)是提供某种类型的全局变量,可从lambda/函数访问。例如,您可以创建一个传统的functor对象,并为其提供一个引用某个唯一(全局/静态)实例的静态成员函数C++;将捕获作为函数指针的lambda 我玩的是C++ LAMBDAS,它们的隐式转换为函数指针。我的起始示例是使用它们作为ftw函数的回调。这正如预期的那样有效 #include <ftw.h> #include <iostream> using namespace std; int main() { auto callback = [](const char *fpath, const struct stat *sb, int typeflag) -> int { cout << fpath << endl; return 0; }; int ret = ftw("/etc", callback, 1); return ret; } #包括 #包括 使用名称空间std; int main() { 自动回调=[](常量字符*fpath,常量结构stat*sb, int-typeflag)->int{ cout,c++,lambda,function-pointers,c++11,C++,Lambda,Function Pointers,C++11,由于捕获lambda需要保留一个状态,因此实际上没有简单的“解决方法”,因为它们不仅仅是普通函数。函数指针的意义在于它指向一个单一的全局函数,而这些信息没有空间容纳状态 最接近的解决方法(本质上放弃状态性)是提供某种类型的全局变量,可从lambda/函数访问。例如,您可以创建一个传统的functor对象,并为其提供一个引用某个唯一(全局/静态)实例的静态成员函数 但这有点违背了捕获兰姆达斯的全部目的。我刚刚遇到了这个问题 代码在没有lambda捕获的情况下可以正常编译,但lambda捕获存在类型
但这有点违背了捕获兰姆达斯的全部目的。我刚刚遇到了这个问题 代码在没有lambda捕获的情况下可以正常编译,但lambda捕获存在类型转换错误 使用C++11的解决方案是使用
std::function
(编辑:本例后面显示了另一个不需要修改函数签名的解决方案)。您也可以使用boost::function
(实际上运行得更快).示例代码-更改以使其能够编译,使用gcc 4.7.1编译:
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
int ftw(const char *fpath, std::function<int (const char *path)> callback) {
return callback(fpath);
}
int main()
{
vector<string> entries;
std::function<int (const char *fpath)> callback = [&](const char *fpath) -> int {
entries.push_back(fpath);
return 0;
};
int ret = ftw("/etc", callback);
for (auto entry : entries ) {
cout << entry << endl;
}
return ret;
}
#包括
#包括
#包括
使用名称空间std;
intftw(常量字符*fpath,std::函数回调){
返回回调(fpath);
}
int main()
{
向量条目;
std::函数回调=[&](const char*fpath)->int{
条目。推回(fpath);
返回0;
};
int-ret=ftw(“/etc”,回调);
用于(自动输入:输入){
我们在这里找到了答案:
它将lambda指针
转换为void*
并在需要时转换回
作废*
:
自动失效函数=新的decltype(to_函数(lambda))(to_函数(lambda))
void*
:
自动功能=静态转换将捕获lambda转换为函数指针是一种很有技巧的方法,但在使用它时需要小心: 您的代码将如下所示(警告:brain compile):
intmain()
{
向量条目;
auto const callback=cify([&](const char*fpath,const struct stat*sb,
int-typeflag)->int{
条目。推回(fpath);
返回0;
});
int-ret=ftw(“/etc”,回调,1);
用于(自动输入:输入){
呵呵,这是个老问题,但还是
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
// We dont try to outsmart the compiler...
template<typename T>
int ftw(const char *fpath, T callback) {
return callback(fpath);
}
int main()
{
vector<string> entries;
// ... now the @ftw can accept lambda
int ret = ftw("/etc", [&](const char *fpath) -> int {
entries.push_back(fpath);
return 0;
});
// ... and function object too
struct _ {
static int lambda(vector<string>& entries, const char* fpath) {
entries.push_back(fpath);
return 0;
}
};
ret = ftw("/tmp", bind(_::lambda, ref(entries), placeholders::_1));
for (auto entry : entries ) {
cout << entry << endl;
}
return ret;
}
#包括
#包括
#包括
使用名称空间std;
//我们不会试图智取编译器。。。
样板
int ftw(常量字符*fpath,T回调){
返回回调(fpath);
}
int main()
{
向量条目;
//…现在@ftw可以接受lambda
int ret=ftw(“/etc”,[&](常量字符*fpath)->int{
条目。推回(fpath);
返回0;
});
//…还有函数对象
结构{
静态int lambda(向量和条目,常量字符*fpath){
条目。推回(fpath);
返回0;
}
};
ret=ftw(“/tmp”,bind(216;::lambda,ref(条目),占位符::1));
用于(自动输入:输入){
cout原创
Lambda函数非常方便,并且减少了代码。在我的例子中,我需要Lambda进行并行编程。但是它需要捕获和函数指针。我的解决方案就在这里。但是要注意捕获的变量的范围
template<typename Tret, typename T>
Tret lambda_ptr_exec(T* v) {
return (Tret) (*v)();
}
template<typename Tret = void, typename Tfp = Tret(*)(void*), typename T>
Tfp lambda_ptr(T& v) {
return (Tfp) lambda_ptr_exec<Tret, T>;
}
带有返回值的示例
int a = 100;
auto b = [&]() {return a;};
int (*fp)(void*) = lambda_ptr<int>(b);
fp(&b);
将带有捕获的lambda转换为C指针
void (*f1)(void*) = Lambda::ptr(b);
f1(nullptr);
printf("%d\n", a); // 101
也可以这样使用
auto f2 = Lambda::ptr(b);
f2(nullptr);
printf("%d\n", a); // 102
在这种情况下,应使用返回值
int (*f3)(void*) = Lambda::ptr<int>(b);
printf("%d\n", f3(nullptr)); // 103
int(*f3)(void*)=Lambda::ptr(b);
printf(“%d\n”,f3(nullptr));//103
如果使用了数据
auto b2 = [&](void* data) {return *(int*)(data) + a;};
int (*f4)(void*) = Lambda::ptr<int>(b2);
int data = 5;
printf("%d\n", f4(&data)); // 108
autob2=[&](void*data){return*(int*)(data)+a;};
int(*f4)(void*)=Lambda::ptr(b2);
int数据=5;
printf(“%d\n”,f4(&data));//108
使用局部全局(静态)方法,可以按以下步骤进行
template <class F>
auto cify_no_args(F&& f) {
static F fn = std::forward<F>(f);
return [] {
return fn();
};
}
因此,用法将是
some_c_func(cify_no_args([&] {
// code
}));
这是因为每个lambda都有一个唯一的签名,所以使其成为静态并不成问题
template <class F>
struct lambda_traits : lambda_traits<decltype(&F::operator())>
{ };
template <typename F, typename R, typename... Args>
struct lambda_traits<R(F::*)(Args...)> : lambda_traits<R(F::*)(Args...) const>
{ };
template <class F, class R, class... Args>
struct lambda_traits<R(F::*)(Args...) const> {
using pointer = typename std::add_pointer<R(Args...)>::type;
static pointer cify(F&& f) {
static F fn = std::forward<F>(f);
return [](Args... args) {
return fn(std::forward<Args>(args)...);
};
}
};
template <class F>
inline lambda_traits<F>::pointer cify(F&& f) {
return lambda_traits<F>::cify(std::forward<F>(f));
}
我的解决方案是,只使用一个函数指针来引用静态lambda
typedef int (* MYPROC)(int);
void fun(MYPROC m)
{
cout << m(100) << endl;
}
template<class T>
void fun2(T f)
{
cout << f(100) << endl;
}
void useLambdaAsFunPtr()
{
int p = 7;
auto f = [p](int a)->int {return a * p; };
//fun(f);//error
fun2(f);
}
void useLambdaAsFunPtr2()
{
int p = 7;
static auto f = [p](int a)->int {return a * p; };
MYPROC ff = [](int i)->int { return f(i); };
//here, it works!
fun(ff);
}
void test()
{
useLambdaAsFunPtr2();
}
typedef int(*MYPROC)(int);
虚无乐趣(MYPROC m)
{
一个更简洁的解决方案是将lambda封装在适配器中,假设函数指针有一个上下文参数。@RaymondChen:好吧,如果您可以自由定义函数的使用方式,那么是的,这是一个选项。不过在这种情况下,只需将参数作为lambda本身的参数就更容易了!@KerrekSB-put名称空间中的全局变量
,并将它们标记为thread\u local
,这是我为解决类似问题而选择的ftw
方法。“函数指针指向单个全局函数,而此信息没有空间容纳状态。”->像Java这样的语言怎么能做到这一点呢?当然,因为单个全局函数是在运行时创建的,并嵌入状态(或者更确切地说是对状态的引用)在它自己的代码中,这就是整个点——不应该有一个单一的全局函数,而是多个全局函数——每次运行时使用lambda。一个C++中真的没有什么可以做到吗?(我认为STD:函数是为那个目的而精确地制作的)答案是否定的,长的答案涉及操作符重载。不管怎样,我的观点是:java是一种不同于C++的语言;java没有指针(或者可重载的调用操作符),而且比较不太好。
auto f2 = Lambda::ptr(b);
f2(nullptr);
printf("%d\n", a); // 102
int (*f3)(void*) = Lambda::ptr<int>(b);
printf("%d\n", f3(nullptr)); // 103
auto b2 = [&](void* data) {return *(int*)(data) + a;};
int (*f4)(void*) = Lambda::ptr<int>(b2);
int data = 5;
printf("%d\n", f4(&data)); // 108
template <class F>
auto cify_no_args(F&& f) {
static F fn = std::forward<F>(f);
return [] {
return fn();
};
}
void some_c_func(void (*callback)());
some_c_func(cify_no_args([&] {
// code
}));
template <class F>
struct lambda_traits : lambda_traits<decltype(&F::operator())>
{ };
template <typename F, typename R, typename... Args>
struct lambda_traits<R(F::*)(Args...)> : lambda_traits<R(F::*)(Args...) const>
{ };
template <class F, class R, class... Args>
struct lambda_traits<R(F::*)(Args...) const> {
using pointer = typename std::add_pointer<R(Args...)>::type;
static pointer cify(F&& f) {
static F fn = std::forward<F>(f);
return [](Args... args) {
return fn(std::forward<Args>(args)...);
};
}
};
template <class F>
inline lambda_traits<F>::pointer cify(F&& f) {
return lambda_traits<F>::cify(std::forward<F>(f));
}
void some_c_func(int (*callback)(some_struct*, float));
some_c_func(cify([&](some_struct* s, float f) {
// making use of "s" and "f"
return 0;
}));
typedef int (* MYPROC)(int);
void fun(MYPROC m)
{
cout << m(100) << endl;
}
template<class T>
void fun2(T f)
{
cout << f(100) << endl;
}
void useLambdaAsFunPtr()
{
int p = 7;
auto f = [p](int a)->int {return a * p; };
//fun(f);//error
fun2(f);
}
void useLambdaAsFunPtr2()
{
int p = 7;
static auto f = [p](int a)->int {return a * p; };
MYPROC ff = [](int i)->int { return f(i); };
//here, it works!
fun(ff);
}
void test()
{
useLambdaAsFunPtr2();
}