我尝试了这个,以及它的一些变化:
template<class T>
class Ptr {
public:
Ptr(T* ptr) : p(ptr) {}
~Ptr() { if(p) delete p; }
template<class Method>
Method operator ->* (Method method)
{
return p->*method;
}
private:
T *p;
};
class Foo {
public:
void foo(int) {}
int bar() { return 3; }
};
int main() {
Ptr<Foo> p(new Foo());
void (Foo::*method)(int) = &Foo::foo;
int (Foo::*method2)() = &Foo::bar;
(p->*method)(5);
(p->*method2)();
return 0;
}
但doesn't work。问题是我真的不知道期待什么作为参数或返回什么。关于这一点的标准对我来说是不可理解的,因为Google没有提出任何有用的信息,我想我并不孤单。
编辑:另一次尝试,使用C ++ 0x:http://ideone.com/lMlyB
答案 0 :(得分:8)
operator->*
的返回表示被调用过程中的一个函数,唯一缺失的部分是参数。因此,您必须返回一个仿函数,该仿函数使用给定的参数调用给定对象上的给定函数:
// PTMF = pointer to member function
template<class Obj>
struct PTMF_Object{
typedef int (Obj::*ptmf)(double,std::string); // example signature
PTMF_Object(Obj* obj, ptmf func)
: obj_(obj)
, func_(func)
{}
int operator()(double d, std::string str){
return (obj_->*func_)(d,str);
}
Obj* obj_;
ptmf func_;
};
template<class T>
struct SmartPtr{
// ...
PTMF_Object<T> operator->*(PTMF_Object<T>::ptmf func){
return PTMF_Object<T>(p, func);
}
// ...
};
int main(){
SmartPtr<Foo> pf(new Foo());
typedef int (Foo::*Foo_ptmf)(double,std::string);
Foo_ptmf method = &Foo::bar;
(pf->*method)(5.4, "oh hi");
}
<强> EDIT2 强>
Here是Scott Meyers关于这个主题的优秀pdf(这是关于重载operator->*
的唯一优秀文献,尽管它来自1999年)。
修改强>
如果您的编译器支持可变参数模板,那么这是一个:http://ideone.com/B6kRF
答案 1 :(得分:2)
我回到了这个问题,我找到了一个简单的解决方案:
template<class Ret, class... Args>
auto operator ->* (Ret (T::*method)(Args...)) -> std::function<Ret(Args...)>
{
return [this, method](Args&&... args) -> Ret {
return (this->p->*method)(std::forward<Args>(args)...);
};
}
可以找到完整测试用例的实现here。
我在这个解决方案中唯一不喜欢的是使用std::function
。如果有人知道直接退回lambda的方法,请告诉我。我有预感,因为lambda类型的定义方式可能无法实现。
答案 2 :(得分:1)
operator->*
的返回类型应该是一个可以作为函数调用的对象。
所以你可能必须将指向成员函数调用的指针转发给一个重载operator()
(一个闭包)的对象,如果你没有方便的可变参数模板,那就特别痛苦了。
如果你有C ++ 0X,你有闭包和可变参数模板,你的问题可以用几行通用代码来解决。
如果你不这样做,你将不得不使用宏技巧来模拟可变参数模板,这是不有趣(即使有些人认为相反)。