可以使用以下方式“剥离”函数参数类型:
void foo_double(double a)
{
}
void foo_int(int a)
{
}
template <class R, class A0>
void bar(R (*fp)(A0))
{
// Do something related with A0
}
int main()
{
bar(foo_double); // A0 is double
bar(foo_int); // A0 is int
}
是否可以对类构造函数执行相同的“参数类型剥离”?
我相信我没有在原始代码段中清楚地解释自己。这是完整的方案。
我有多个类C1,...,Cn
,我需要将它作为函数公开给python。让我们假设所有类都有一个共同的void Run()
方法。但是,这些类的构造函数接受不同的参数。要向python公开函数,我使用boost.python,它会在处理所有类型转换(主要是基元)时自动将函数导出到适当的python函数。
我的第一个解决方案是:
class C1
{
public:
C1() {}
void Run();
};
class C2
{
public:
C2(double a) {}
void Run();
};
template <class T>
void python_wrapper()
{
T instance();
instance.Run();
}
template <class T, class A0>
void python_wrapper(A0 a0)
{
T instance(a0);
instance.Run();
}
BOOST_PYTHON_MODULE(_pythonmodule)
{
// This is boost.python stuff
python::def("f1", python_wrapper<C1>);
python::def("f2", python_wrapper<C2, double>);
}
而且......它有效。
我现在要完成的是在推断构造函数参数类型时使用python_wrapper<C2>
而不是python_wrapper<C2, double>
。
正如我在原帖中所展示的那样。如果我要包装函数而不是类,我可以完成类似的事情。
答案 0 :(得分:0)
您不能获取构造函数的地址(C ++ 98 Standard 12.1 / 12构造函数 - “12.1-12构造函数 - ”不应该使用构造函数的地址。)
如果所有类共享一个基类,那么你可以创建一个工厂,但是没有C ++ 11可变参数模板我不知道如何进行参数转发。
template <typename type>
static type* construct(){
return new type();
}
auto value = &construct<int>;
您现在有一个可绑定函数,在调用时会生成类型*
auto value = &construct<int>;
int* newInt = (*value)();
delete newInt;
为了允许不同的构造函数输入,这使用C ++ 11
template <typename type>
class constructor {
public:
template<typename ...Args>
static std::shared_ptr<type> alloc(Args&& ...args){
return std::shared_ptr<type>(new type(std::forward<Args>(args)...));
}
// placement new
template<typename ...Args>
static std::shared_ptr<type> realloc( std::shared_ptr<type>& object,Args&& ...args){
(new (&(*object)) type(std::forward<Args>(args)...));
return object;
}
};
class fooBar{
public:
fooBar(int x,float f){
}
};
typedef std::shared_ptr<fooBar> fooBarPtr;
用法:
fooBarPtr a = constructor<fooBar>::alloc(5,0.0f);
或者这可能更接近操作的需要。
class fooy{
int _x = 0;
public:
fooy(int argCount, va_list& list){
if( argCount > 0){
_x = va_arg(list, int);
}
}
};
template <typename type>
std::shared_ptr<type> alloc(int argCount,...) {
va_list list;
va_start(list, argCount);
auto result = std::shared_ptr<type>( new type(argCount,list) );
va_end(list);
return result;
}
用法:
auto foo1 = alloc<fooy>(0); // passing zero args
auto foo2 = alloc<fooy>(1,1234); // passing one arg
答案 1 :(得分:0)
由于您不想更改现有的类,因此无法自动化在C ++中对这些类进行演绎。您可以通过从源代码中提取签名信息,在C ++之外为这些类执行此操作。这种提取可以手动完成,也可以通过脚本甚至是C ++程序自动完成。
对于每个现有的类E,使用提取的信息来定义类模板的特化,该类模板定义静态成员函数func
,该函数将其参数(如果有的话)传递给类E的构造函数并调用Run
方法。
对于新类,只需要他们定义func
,并让类模板默认使用现有的func
。
然后,一般的Python包装器定义代码可以推断出func
的参数,你已经告诉它你知道该怎么做。
这意味着定义类的人只需要开始为新的类添加func
。
稍微高一点,我认为值得利用一些时间让相关人员参与进来,并了解如何通过定义多个类别来采用和巩固一个ungood设计。目标是防止将来再次发生这种情况。我认为,如何应对这种情况取决于它是如何发生的。
答案 2 :(得分:0)
我不确定这将如何与python :: def进行交互,但通常这是可变参数模板的用途:
struct C1{
C1(){}
void run(){}
};
struct C2{
C2(int){}
void run(){}
};
template<typename CLASS, typename... PARAMS>
void call(PARAMS... params) {
CLASS inst(params...);
inst.run();
}
main() {
call<C1>();
call<C2>(42);
}
它是c ++ 11,但自4.3版以来在gcc中受支持