C++ 如何编写一个类来接受函数指针和/或函子,就像智能指针接受自定义删除器一样?
我试图编写一个类,该类接受一个函数指针和/或一个函子,以后由该类作为用户。 为了更好地说明我想做什么:C++ 如何编写一个类来接受函数指针和/或函子,就像智能指针接受自定义删除器一样?,c++,boost,function-pointers,functor,tr1,C++,Boost,Function Pointers,Functor,Tr1,我试图编写一个类,该类接受一个函数指针和/或一个函子,以后由该类作为用户。 为了更好地说明我想做什么: template <typename T> class Holder { private: T *m_ptr; <something> m_func; public: Holder(T *ptr) : m_ptr(ptr), m_func(NULL) { } Holder(T *ptr, <something> func) : m_p
template <typename T> class Holder {
private:
T *m_ptr;
<something> m_func;
public:
Holder(T *ptr) : m_ptr(ptr), m_func(NULL) {
}
Holder(T *ptr, <something> func) : m_ptr(ptr), m_func(func) {
}
~Holder() {
if (m_func) {
m_func(m_ptr);
} else {
delete m_ptr;
}
}
};
模板类持有者{
私人:
T*m_ptr;
m_func;
公众:
持有者(T*ptr):m_ptr(ptr),m_func(空){
}
持有人(T*ptr,func):m_ptr(ptr),m_func(func){
}
~Holder(){
if(m_func){
m_func(m_ptr);
}否则{
删除m_ptr;
}
}
};
考虑到我想处理这种类型的对象:
class MyClass {
public:
void describe() {
cout << "Bla bla bla ...";
}
};
class-MyClass{
公众:
void descripe(){
cout一个明显的解决方案是使用boost::function
或std::function
。但是,如果希望避免这些对象增加的开销,可以让Holder
接受可调用的模板参数:
template <typename T, class F>
class Holder
{
private:
T *m_ptr;
F m_func;
//...
答案是:类型擦除
实现并不是那么简单,我建议稍微阅读一下类型擦除(就像我刚才做的那样!)
首先,您需要创建类型擦除设备:
class ActionBase {
public:
virtual ~ActionBase() { }
virtual bool DoIt() = 0;
};
template<typename P>
class ActionP : public ActionBase {
private:
P *ptr;
public:
ActionP(P *p) : ptr(p) { }
virtual bool DoIt() {
cout << "Standard action (nothing to do)..." << endl;
return true;
}
};
template<typename P, class A>
class ActionPA : public ActionBase {
private:
P *ptr;
A action;
public:
ActionPA(P *p, A & a ) : ptr(p), action(a) { }
virtual bool DoIt() { return action(ptr); }
};
希望它对其他人有用。您可以使用boost::function
,请参见此处示例:c++11和MyClassFunctor()中还有std::function
没有做你认为它能做的事。丢失参数。@g-makulik没有很好的理由这样做,这会使代码变得不必要的复杂-想象一下,如果每次声明智能指针时,你都必须指定另一个模板参数。boost::函数和C++11 std::函数帮助很大。但是,我正在考虑这样做这在普通的C++03中是可能的吗?这似乎很有希望。我想知道boost如何在没有辅助函数的情况下使用C++03实现这一点。你有什么线索吗?@Marcus如果你的意思是shared\u ptr
如何接受自定义的删除器,那就是它如何做到的。那里的“辅助函数”有一个参数化的构造函数(比如template shared\u ptr(Y*p,D D)
)。请记住,扣除参数类型的唯一方法是使用[member-]函数模板。正是Igor,但是您需要使用类型擦除才能同时使用函数指针和函子。请检查我发布的解决方案。@Marcus不,您没有。类型擦除实际上是一个非模板对象(未被可调用类型参数化)这将允许存储任何可调用的,因此它实际上是std::function
。但是如果您对这样的开销没问题,只需使用std::function
,就无需重新设计。OTOH,使用模板解决方案,您没有这样的开销(但还有其他已知的权衡)理解Igor。STD的问题是:函数是C++ 11,不是吗?我现在试图避免C++ 11,因为大多数时候我不为PC编程,而是嵌入C++。即使是强硬的,你也是对的。谢谢你的帮助。
template <typename T, class F>
class Holder
{
private:
T *m_ptr;
F m_func;
//...
// depending on the nature of your functors, consider passing by const &
template<typename T, class F>
Holder<T, F> make_holder(T *t, F f)
{
return Holder<T, F>(t, f);
}
auto holder = make_holder(myClass, &myClassDeleter);
// or:
auto holder = make_holder(myClass, functor);
class ActionBase {
public:
virtual ~ActionBase() { }
virtual bool DoIt() = 0;
};
template<typename P>
class ActionP : public ActionBase {
private:
P *ptr;
public:
ActionP(P *p) : ptr(p) { }
virtual bool DoIt() {
cout << "Standard action (nothing to do)..." << endl;
return true;
}
};
template<typename P, class A>
class ActionPA : public ActionBase {
private:
P *ptr;
A action;
public:
ActionPA(P *p, A & a ) : ptr(p), action(a) { }
virtual bool DoIt() { return action(ptr); }
};
template<typename T>
class Holder {
private:
// Avoid object copy and assignment.
Holder(const Holder<T> &rhs);
Holder<T>& operator=(const Holder<T> &rhs);
protected:
T* ptr;
ActionBase *action;
public:
template<typename U> Holder(U *ptr) : ptr(ptr), action(new ActionP<U>(ptr)) { }
template<typename U, class A> Holder(U* p, A a) : ptr(p), action(new ActionPA<U, A>(p, a)) { }
virtual ~Holder() { delete ptr; delete action; }
bool DoAction() {
return this->action->DoIt();
}
};
template<typename T>
class ActionFunctor {
public:
bool operator()(T* instance) const {
cout << "Action operator..." << endl;
// Simple operation: set the value to 3 times the original value (works for int and string!!)
instance->Set(instance->Get() + instance->Get());
return true;
}
};
template<typename T>
bool ActionFunc(T* instance) {
cout << "Action function..." << endl;
// Simple operation: set the value to 3 times the original value (works for int and string!!)
instance->Set(instance->Get() + instance->Get() + instance->Get());
return true;
}
int main() {
{
cout << "First test:" << endl;
ActionFunctor<X> actionX;
Holder<X> x1(new X(1), &ActionFunc<X>);
Holder<X> x2(new X(10), actionX);
Holder<X> x3(new X(100));
x1.DoAction();
x2.DoAction();
x3.DoAction();
}
{
cout << "Second test:" << endl;
ActionFunctor<Y> actionY;
Holder<Y> y1(new Y("A"), &ActionFunc<Y>);
Holder<Y> y2(new Y("BB"), actionY);
Holder<Y> y3(new Y("CCC"));
y1.DoAction();
y2.DoAction();
y3.DoAction();
}
return 0;
}
First test:
X constructor: 1
X constructor: 10
X constructor: 100
Action function...
Action operator...
Standard action (nothing to do)...
X desstructor: 100
X desstructor: 20
X desstructor: 3
Second test:
Y constructor: "A"
Y constructor: "BB"
Y constructor: "CCC"
Action function...
Action operator...
Standard action (nothing to do)...
Y destructor: "CCC" ...
Y destructor: "BBBB" ...
Y destructor: "AAA" ...