确定类构造函数参数的数量和类型(C++?
Determine the number and type of the class constructor's parameters in C++?
如何确定类构造函数参数的数量和类型?对于成员函数执行此操作只是小菜一碟:
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++预处理器,可以扫描所有源文件,并拥有所有类,方法,ctor及其确切原型的数据库。我需要基于此生成一些存根。
如果我正确理解了您的要求,您需要一个函数,您可以获取其地址,该函数告诉您构造函数或构造函数的参数类型。
#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>());
我会建议解决此问题的方法。我经常使用"静态实例构造函数"模式 - 例如,用于反序列化类的实例,该类是子类化的,例如。
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);
};
您应该能够检索指向静态函数的指针并将其传递给工具方法。
编辑:
既然你解释了,你真正想做什么,我建议使用类工厂(首选)或静态构造函数,如前所述。这样,您始终可以检索指向所需方法(静态或非静态)的指针,并在当前体系结构中使用它(基于您提供的代码)。
另外,看看 C#/11 中的 std::function<> 和 lambda。我想,它们可能会使您的架构更简单。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 构造函数正在调用一个使用当前类类型的函数
- 我应该使用什么来代替void作为变体中的替代类型之一
- 类中的字符串不命名类型