我想编写一个可以将非静态成员函数转换为C风格函数指针的适配器。这是我现在得到的(参见下面的代码片段),但目前的解决方案并不常见。我想让int (T::*Func)(int)
接受变量参数。
还有必要让CObjectT::f
和StoreVals::display
具有相同的签名。
最终目标是将C ++成员函数与C库连接。
class StoreVals
{
int val;
public:
int display(int k) { cout << k << endl; return 0; }
};
template<class T, int (T::*Func)(int)>
class CObjectT
{
public:
/*
* The signagure of 'f(...)' should change by the argument of template.
* They must be the same, but i don't know how to achieve this goal.
*/
static int f(int i)
{
T obj;
return (obj.*Func)(i);
}
};
void main()
{
CObjectT<StoreVals, &StoreVals::display>::f(7);
auto function_t = &CObjectT<StoreVals, &StoreVals::display>::f;
// Now it's a C-style function pointer
cout << typeid(function_t).name() << endl;
}
答案 0 :(得分:3)
我认为不可能根据模板参数动态更改函数名称,但您可以根据模板参数更改参数/返回类型。它确实需要模板声明中的一些额外的类型信息,但它确实允许你想要的。
#include <iostream>
#include <utility>
template< typename T, T t >
class Delegate;
template< typename R, typename C, typename... Args, R ( C::*F ) ( Args... )>
class Delegate< R ( C::*)( Args... ), F > {
public:
template< typename... Ts >
static R invoke( Ts&&... args ) {
C t;
return ( t.*F )( std::forward< Ts >( args )... );
}
};
template< typename R, typename... Args, R ( *F ) ( Args... ) >
class Delegate< R ( * ) ( Args... ), F > {
public:
template< typename... Ts >
static R invoke( Ts&&... args ) {
return F( std::forward< Ts >( args )... );
}
};
void print( int v ) {
std::cout << "Static: " << v << std::endl;
}
class Class {
void print( int v ) {
std::cout << "Class: " << v << std::endl;
}
};
int main( int argc, char** argv ) {
Delegate< void ( * )( int ), &print >::invoke( 1 );
Delegate< void ( Class::* ) ( int ), &Class::print >::invoke( 1 );
return 0;
}
输出:
Static: 1
Class: 1
这确实使用C ++ 11的可变参数模板和Rvalue引用来实现完美转发。这就是为什么你在函数调用中看到奇怪的std::forward< Args >( args )...
。
这不适用于variadic参数函数,例如printf等。它可能是可能的,但需要更多模板黑魔法,我没有时间编写和测试。
答案 1 :(得分:2)
如果要与C接口,则无法使用模板,也无法使用成员函数(甚至是静态)。唯一的方法是诚实的手写extern "C"
功能。模板或成员函数不能具有C链接。
如果你想为了方便而牺牲便携性,可以这样做:
#define TYPE_AND_VALUE(x) decltype(x),x
#define MemFuncTypeAdapter(x) MemFuncTypeAdapterStruct<TYPE_AND_VALUE(x)>
extern "C"
{
int (*cfunc)(struct A*, int);
}
template <typename MemFuncType> struct MemFuncTypes;
template <typename Class, typename Ret, typename... Args>
struct MemFuncTypes<Ret (Class::*)(Args...)>
{
using RetType = Ret;
using ClassType = Class;
};
template <typename MemFuncType, MemFuncType memFunc>
struct MemFuncTypeAdapterStruct
{
using RetType = typename MemFuncTypes<MemFuncType>::RetType;
using ClassType = typename MemFuncTypes<MemFuncType>::ClassType;
template <typename... Args>
static RetType func (ClassType* c, Args... args)
{
return (c->*memFunc)(args...);
}
};
struct A
{
A() : a(33) {};
int a;
int plus (int b) { return a + b; }
};
int main ()
{
MemFuncTypeAdapter(&A::plus) aplus;
A a;
aplus.func(&a, 22);
cfunc = &MemFuncTypeAdapter(&A::plus)::func; //<- C interface here
}
注释
Class*
参数。请参阅评论以获得对此的解释。typename(x), x
。希望未来的C ++标准能够解决它。