C++ 将类成员函数绑定到c函数

C++ 将类成员函数绑定到c函数,c++,templates,C++,Templates,下面我有一个将类成员函数绑定到全局函数的概念。这主要是用C++实现C风格回调函数的实现。这可以用更好的方法实现(例如,不使用final宏或typeof,或使用C++0x功能) #包括 使用名称空间std; 模板结构mf\U包装器\U帮助器; 模板 结构mf\U包装器\U帮助器 { 模板 静态R包装器(T*foo){return(foo->*F)(;} }; 模板 结构mf\U包装器\U帮助器 { 模板 静态R包装器(T*foo,T1 arg1){return(foo->*F)(arg1);} }

下面我有一个将类成员函数绑定到全局函数的概念。这主要是用C++实现C风格回调函数的实现。这可以用更好的方法实现(例如,不使用final宏或
typeof
,或使用C++0x功能)

#包括
使用名称空间std;
模板结构mf\U包装器\U帮助器;
模板
结构mf\U包装器\U帮助器
{
模板
静态R包装器(T*foo){return(foo->*F)(;}
};
模板
结构mf\U包装器\U帮助器
{
模板
静态R包装器(T*foo,T1 arg1){return(foo->*F)(arg1);}
};
#定义绑定\u MF(MF)\
mf\u wrapper\u helper::wrapper
结构Foo
{

void x(){cout我认为唯一能完美工作的技术是为希望在C回调中调用的每个成员函数编写一个C包装函数;即:

extern "C" void Foo_x(Foo *foo)
{
    foo->x();
}

extern "C" void Foo_x1(Foo *foo, int i)
{
    foo->x1(i);
}
您还可以使用C++0x的lambda表达式,它隐式转换为指向函数的指针,该函数的参数和返回类型与闭包类型的函数调用运算符相同。但是,请记住,函数类型的语言链接是“C++”,而不是“C”

EDIT:经过一点实验后,我提出了以下模板函数,它们返回调用给定成员函数的lambda:

template <typename return_t, class base, typename... arg_types>
std::function<return_t (base*, arg_types...)> make_lambda_to_call_member_function(return_t (base::*mem_fn)(arg_types...)) 
{
    return [mem_fn] (base *o, arg_types... args) -> return_t {
        (o->*mem_fn)(args...);
    };
}

template <typename return_t, class base, typename... arg_types>
std::function<return_t (const base*, arg_types...)> make_lambda_to_call_member_function(return_t (base::*cmem_fn)(arg_types...) const) 
{
    return [cmem_fn] (const base *o, arg_types... args) -> return_t {
        (o->*cmem_fn)(args...);
    };
}
然后使用模板
make_lambda__调用_member_函数
如下所示:

auto fn = make_lambda_to_call_member_function(&Foo::x);
fn(&foo);

auto fn1 = make_lambda_to_call_member_function(&Foo::x1);
fn1(&foo, 314);

auto fn2 = make_lambda_to_call_member_function(&Foo::cx1);
fn2(&foo, 44.832f);
但是,请注意,返回的lambda对象不会隐式转换为函数指针,因为lambda表达式使用lambda捕获

C++0x的最新草案n3225规定:

没有lambda捕获的lambda表达式的闭包类型具有一个公共非虚拟非显式const转换函数,该函数指向与闭包类型的函数调用运算符具有相同参数和返回类型的函数指针。此转换函数返回的值应为调用时具有相同参数和返回类型的函数的地址与调用闭包类型的函数调用操作符的效果相同

以下是非法的:

void (*fn5)(Foo*) = make_lambda_to_call_member_function(&Foo::x);

您使用的编译器是什么?如果您可以使用C++0x,只需使用较少捕获的lambda,就可以将它们转换为函数指针。另外,为什么要在
main
中动态分配某些内容?忽略
new
-这与问题无关。我使用GCC 4.5和ICC 11.1。不确定lambda在这方面有何帮助,因为
lambda函数s是依赖于实现类型的函数对象
。事实上,我不太了解C++0x,代码示例很受欢迎。投票结束,因为这个问题可能更适合@klimkin:就像我说的,你可以制作一个就地lambda,它可以转换为函数指针。我们只需要知道C++0x是否是一个选项。“忽略那个新的-对这个问题不重要。”没错,那为什么它会在那里?:)@John:我不知道,也许它是一个官方的交换网站,但现在它应该放在这里。(忽略这个,我认为代码审查网站是不必要的。)有一点值得一提,虽然不是真正的答案:C++0x关键字
decltype
与g++编译器扩展
typeof
基本上是一样的。关于链接类型,这是一个很好的观点。我发现使用lambda有一个问题-所有参数类型都应该完全列出。对于模板版本,所有类型都是用编译器计算的。是有可能制作一个以成员函数为参数的lambda函数模板吗?@klimkin:我更新了我的答案,提供了更多信息。为了回答你的问题,可以编写一个模板函数,返回调用给定成员函数的lambda对象,但该lambda对象不能再转换为函数指针。
template <typename return_t, class base, typename... arg_types>
std::function<return_t (base*, arg_types...)> make_lambda_to_call_member_function(return_t (base::*mem_fn)(arg_types...)) 
{
    return [mem_fn] (base *o, arg_types... args) -> return_t {
        (o->*mem_fn)(args...);
    };
}

template <typename return_t, class base, typename... arg_types>
std::function<return_t (const base*, arg_types...)> make_lambda_to_call_member_function(return_t (base::*cmem_fn)(arg_types...) const) 
{
    return [cmem_fn] (const base *o, arg_types... args) -> return_t {
        (o->*cmem_fn)(args...);
    };
}
struct Foo
{
    void x() { cout << "Foo::x()" << endl; }
    void x1(int i) { cout << "Foo::x1(" << i << ")" << endl; }
    void cx1(float f) const { cout << "Foo::cx1(" << f << ")" << endl; }
};
auto fn = make_lambda_to_call_member_function(&Foo::x);
fn(&foo);

auto fn1 = make_lambda_to_call_member_function(&Foo::x1);
fn1(&foo, 314);

auto fn2 = make_lambda_to_call_member_function(&Foo::cx1);
fn2(&foo, 44.832f);
void (*fn5)(Foo*) = make_lambda_to_call_member_function(&Foo::x);