如何重载 ->* 运算符?

How to overload the ->* operator?

本文关键字:gt 运算符 何重载 重载      更新时间:2023-10-16

我尝试了这个,以及它的一些变化:

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;
}

但是它不起作用。问题是,我真的不知道期望作为参数的是什么,或者返回什么。这方面的标准对我来说是不可理解的,既然谷歌没有提出任何有用的东西,我想我不是一个人。

编辑:另一个尝试,与c++ 0 x: http://ideone.com/lMlyB

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
这是Scott Meyers关于这个话题的优秀pdf(这是关于超载operator->*的唯一好的文献,尽管它来自1999年)。

编辑
这里有一个,如果你的编译器支持可变模板:http://ideone.com/B6kRF

我回到这个问题,我发现了一个简单的解决方案:

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)...);
  };
}

完整测试用例的实现可以在这里找到。

在这个解决方案中我唯一不喜欢的是std::function的使用。如果有人知道直接返回lambda的方法,请告诉我。我有一种预感,由于lambda类型的定义方式,这可能是不可能的。

在IIRC中,operator->*的返回类型应该是一个可以作为函数调用的对象。

因此,您可能不得不将指向成员函数调用的指针转发给重载operator()(闭包)的对象,如果您手边没有可变模板,这尤其令人痛苦。

如果你有c++ 0X,你有闭包和可变模板,你的问题可以用几行泛型代码解决。

如果你不这样做,你将不得不使用宏技巧来模拟可变模板,这是不是有趣的(即使有些人认为相反)。