Æle*_*lex 2 c++ templates pointers abstraction function
我不知道我所要求的是可行的,愚蠢的还是简单的.我最近才开始住在模板函数和类中,我想知道下面的场景是否可行:一个包含要调用的函数指针的类.函数指针不能是特定的,而是抽象的,因此无论何时调用类的构造函数,它都可以接受不同类型的函数指针.当调用类的execute函数时,它会使用参数(或参数)执行在构造时分配的函数指针.基本上,抽象在整个设计中保留,并在用户上留下要传递的函数指针和参数.以下代码尚未经过测试,只是为了演示我正在尝试做的事情:
void (*foo)(double);
void (*bar)(double,double);
void (*blah)(float);
class Instruction
{
protected:
double var_a;
double var_b;
void (*ptr2func)(double);
void (*ptr2func)(double,double);
public:
template <typename F> Instruction(F arg1, F arg2, F arg3)
{
Instruction::ptr2func = &arg1;
var_a = arg2;
var_b = arg3;
};
void execute()
{
(*ptr2func)(var_a);
};
};
Run Code Online (Sandbox Code Playgroud)
我不喜欢我必须在可能的可重载函数指针类中保留一个列表的事实.我怎么可能改进上面的内容以尽可能地概括它,以便它可以与任何类型的函数指针一起使用?请记住,我将保留这些实例化对象的容器并按顺序执行每个函数指针.谢谢 !编辑:也许这个类应该是它自己的模板,以便于使用许多不同的函数指针?编辑2:我找到了解决问题的方法,仅供将来参考,不知道它是否正确,但它有效:
class Instruction
{
protected:
double arg1,arg2,arg3;
public:
virtual void execute() = 0;
};
template <class F> class MoveArm : public Instruction
{
private:
F (func);
public:
template <typename T>
MoveArm(const T& f,double a, double b)
{
arg1 = a;
arg2 = b;
func = &f;
};
void execute()
{
(func)(arg1,arg2);
};
};
Run Code Online (Sandbox Code Playgroud)
但是在导入函数时,它们的函数指针需要是typedef'd:
void doIt(double a, double b)
{
std::cout << "moving arm at: " << a << " " << b << std::endl;
};
typedef void (*ptr2func)(double,double);
int main(int argc, char **argv) {
MoveArm<ptr2func> arm(doIt,0.5,2.3);
arm.execute();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果你能使用的C++ 0x和可变参数模板,您可以通过使用组合实现这一点std::function,std::bind和完美转发:
#include <iostream>
#include <functional>
template <typename Result = void>
class instruction
{
public:
template <typename Func, typename... Args>
instruction(Func func, Args&&... args)
{
m_func = std::bind(func, std::forward<Args>(args)...);
}
Result execute()
{
return m_func();
}
private:
std::function<Result ()> m_func;
};
double add(double a, double b)
{
return (a + b);
}
int main()
{
instruction<double> test(&add, 1.5, 2.0);
std::cout << "result: " << test.execute() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
输出示例:http://ideone.com/9HYWo
在C++ 98/03中,如果您需要支持可变数量的参数,那么您很可能需要自己重载构造函数以获得最多N个参数.你也可以使用boost::function而boost::bind不是std::等价物.然后还存在转发问题的问题,因此要完成转发,您需要根据需要支持的参数量进行指数级的重载.Boost有一个预处理器库,您可以使用它来生成所需的重载,而无需手动编写所有重载; 但这很复杂.
下面是一个如何使用C++ 98/03的例子,假设传递给它的函数instruction不需要通过可修改的引用来获取参数,为此,你还需要重载P1& p1而不是仅仅const P1& p1.
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
template <typename Result = void>
class instruction
{
public:
template <typename Func>
instruction(Func func)
{
m_func = func;
}
template <typename Func, typename P1>
instruction(Func func, const P1& p1)
{
m_func = boost::bind(func, p1);
}
template <typename Func, typename P1, typename P2>
instruction(Func func, const P1& p1, const P2& p2)
{
m_func = boost::bind(func, p1, p2);
}
template <typename Func, typename P1, typename P2, typename P3>
instruction(Func func, const P1& p1, const P2& p2, const P3& p3)
{
m_func = boost::bind(func, p1, p2, p3);
}
Result execute()
{
return m_func();
}
private:
boost::function<Result ()> m_func;
};
double add(double a, double b)
{
return (a + b);
}
int main()
{
instruction<double> test(&add, 1.5, 2.0);
std::cout << "result: " << test.execute() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2354 次 |
| 最近记录: |