如何确定类构造函数参数的数量和类型? 为成员函数执行此操作只是小菜一碟:
template <class T, typename P0, typename P1, typename P2, typename P3>
void BindNativeMethod( void (T::*MethodPtr)(P0, P1, P2, P3) )
{
// we've got 4 params
// use them this way:
std::vector<int> Params;
Params.push_back( TypeToInt<P0>() );
Params.push_back( TypeToInt<P1>() );
Params.push_back( TypeToInt<P2>() );
Params.push_back( TypeToInt<P3>() );
}
template <class T, typename P0, typename P1, typename P2, typename P3, typename P4>
void BindNativeMethod( void (T::*MethodPtr)(P0, P1, P2, P3, P4) )
{
// we've got 5 params
// use them this way:
std::vector<int> Params;
Params.push_back( TypeToInt<P0>() );
Params.push_back( TypeToInt<P1>() );
Params.push_back( TypeToInt<P2>() );
Params.push_back( TypeToInt<P3>() );
Params.push_back( TypeToInt<P4>() );
}
等其他成员。
但是如何处理类构造函数呢?有没有办法找出他们的论点类型?也许有一种根本不同的方法来解决这个问题,因为甚至不可能获取构造函数的地址?
编辑:我有一个C ++预处理器,可以扫描所有源文件,并拥有所有类,方法,ctors及其确切原型的数据库。我需要基于此生成一些存根。
答案 0 :(得分:5)
如果我正确理解了您的要求,您需要一个函数,您可以使用它的地址告诉您构造函数或构造函数的参数类型。
#include <string>
#include <new>
template <typename T, typename P0, typename P1>
T * fake_ctor (T *mem, P0 p0, P1 p1) {
return mem ? new (mem) T(p0, p1) : 0;
}
struct Foo {
Foo (int, int) {}
Foo (int, std::string) {}
};
template <class T, typename P0, typename P1>
void BindClassCtor(T *(*FakeCtor)(T *, P0, P1)) {
std::vector<int> Params;
Params.push_back( TypeToInt<P0>() );
Params.push_back( TypeToInt<P1>() );
}
// PARSER GENERATED CALLS
BindClassCtor<Foo, int, int>(&fake_ctor);
BindClassCtor<Foo, int, std::string>(&fake_ctor);
实现fake_ctor
以实际调用ctor
(即使fake_ctor
本身永远不会被调用)提供了一定程度的编译时间健全性。如果Foo
更改其中一个构造函数而不重新生成BindClassCtor
调用,则可能会导致编译时错误。
编辑:作为奖励,我使用带有可变参数的模板简化了参数绑定。首先是BindParams
模板:
template <typename... T> struct BindParams;
template <typename T, typename P0, typename... PN>
struct BindParams<T, P0, PN...> {
void operator () (std::vector<int> &Params) {
Params.push_back( TypeToInt<P0>() );
BindParams<T, PN...>()(Params);
}
};
template <typename T>
struct BindParams<T> {
void operator () (std::vector<int> &Params) {}
};
现在,fake_ctor
现在是类的集合,因此每个类都可以通过可变参数列表进行实例化:
template <typename... T> struct fake_ctor;
template <typename T>
class fake_ctor<T> {
static T * x (T *mem) {
return mem ? new (mem) T() : 0;
}
decltype(&x) y;
public:
fake_ctor () : y(x) {}
};
template <typename T, typename P0>
class fake_ctor<T, P0> {
static T * x (T *mem, P0 p0) {
return mem ? new (mem) T(p0) : 0;
}
decltype(&x) y;
public:
fake_ctor () : y(x) {}
};
template <typename T, typename P0, typename P1>
class fake_ctor<T, P0, P1> {
static T * x (T *mem, P0 p0, P1 p1) {
return mem ? new (mem) T(p0, p1) : 0;
}
decltype(&x) y;
public:
fake_ctor () : y(x) {}
};
现在粘合剂功能就是这样:
template <typename... T>
void BindClassCtor (fake_ctor<T...>) {
std::vector<int> Params;
BindParams<T...>()(Params);
}
下面是Bar
的构造函数参数绑定的示意图,它有四个构造函数。
struct Bar {
Bar () {}
Bar (int) {}
Bar (int, int) {}
Bar (int, std::string) {}
};
BindClassCtor(fake_ctor<Bar>());
BindClassCtor(fake_ctor<Bar, int>());
BindClassCtor(fake_ctor<Bar, int, int>());
BindClassCtor(fake_ctor<Bar, int, std::string>());
答案 1 :(得分:1)
我建议解决此问题。我经常使用“静态实例构造函数”模式 - 例如,用于反序列化类的实例,这是子类化的,例如。
class BaseClass
{
private:
BaseClass();
virtual void InternalLoad(MyStream s) = 0;
public:
static BaseClass * Create(MyStream s);
};
(...)
BaseClass * BaseClass::Create(MyStream s);
{
int type;
s >> type;
if (type == 0)
{
BaseClass * result = new DerivedClass1(); // DerivedClass1 : public BaseClass
result->InternalLoad(s);
return result;
}
else if (type == 1)
...
}
在您的情况下,您可以轻松使用此模式。只需创建一个静态实例构造函数,它是通用的,并以您希望的方式处理其参数。
修改
我认为,您可以通过以下方式解决问题:
class MyClass
{
private:
MyClass();
public:
template <typename T1, typename T2>
static MyClass * Create(T1 t, T2 u);
};
(...)
template <typename T1, typename T2>
MyClass * MyClass::Create(T1 t, T2 u)
{
MyClass result = new MyClass();
// Process parameters t and u here
return result;
}
然后你可以用以下方式构建类:
MyClass* class = MyClass::Create(5, "Indiana Jones");
请注意,它不是一个解决方案,但(我认为非常优雅)解决方法。
修改
我认为,我现在明白了,你正在尝试做什么并且使用静态方法而不是构造函数实际上仍然可以证明是你的问题的一种解决方法(但这取决于你想对你的信息做什么构造函数参数)。
显然,您应该使用常规参数实现静态构造函数,如:
class MyClass
{
private:
MyClass();
public:
static MyClass * Create(int t, char * u);
};
您应该能够检索指向静态函数的指针并将其传递给您的工具方法。
修改
既然你解释过,你真正想做什么,我建议使用类工厂(首选)或静态构造函数,如前面所提出的。这样,您始终可以检索指向所需方法的指针(静态或非静态),并在当前体系结构中使用它(基于您提供的代码)。
另外,看看std :: function&lt;&gt;和C#/ 11中的lambdas。我想,他们可能会让你的架构更加简单。