为什么auto_ptr不支持op-> *()

时间:2010-07-17 17:25:01

标签: c++ operator-overloading pointer-to-member

auto_ptr(shared_ptr)也尽量让它们尽可能透明;也就是说,理想情况下,您不应该区分是否使用auto_ptr或指向对象的实际指针。考虑:

class MyClass
{
public:
    void foo() {  }
};

MyClass* p = new MyClass;
auto_ptr<MyClass> ap(new MyClassp);

p->foo();       // No notational difference in using real
ap->foo();      // pointers and auto_ptrs

当您尝试通过指向成员的指针调用成员函数时,存在差异,因为auto_ptr显然没有实现op-&gt; *():

void (MyClass::*memfun)() = &MyClass::foo;

(p->*memfun)();         // OK
(ap->*memfun)();        // Error op->*() missing
(ap.get()->*memfun)();  // OK

为什么auto_ptr中不支持op-&gt; *()以及如何实现它(我已经实验了一段时间,但最终放弃了)。

3 个答案:

答案 0 :(得分:8)

正如路德所指出的那样,实施它并非易事 - 但这是有可能的。

你必须

  1. 使用模板,以便可以推导出operator->*的参数类型
  2. 使用重载来处理可能的限定符和多个函数arity
  3. 用于成员函数指针返回一个callabe对象:
    • 绑定到智能指针指向的实例
    • 实现operator(),其签名等同于成员函数
  4. 忽略了momement的限定符,这里它基本上是如何看的(使用C ++ 0x来避免手动重复):

    // pointer to data member:
    
    template<class T, class D>
    D& operator->*(std::auto_ptr<T>& p, D T::*mp) {
        return (*p).*mp;
    }
    
    // pointer to member function:
    
    template<class T, class R, class... Args> struct Callable {
        typedef R (T::*MFP)(Args...);
        MFP mfp;
        T& instance;
    
        Callable(T t, MFP mfp) : instance(t), mfp(mfp) {}
    
        R operator()(Args... a) {
            return (instance.*mfp)(a...);
        }
    };
    
    template<class T, class R, class... Args>
    Callable<T, R, Args...>
    operator->*(std::auto_ptr<T>& p, R (T::*mfp)(Args...)) {
        return Callable<T, R, Args...>(*p, mfp);
    }
    

    但最后,为什么我们可以在第一时间使用绑定成员指针的仿函数时烦恼呢。

    虽然我不能确定它,但如果你结合了

    的知识
    • 实施非常重要
    • 还有一个简单的替代方案((*p).*m

    ......由于此功能所带来的收益与所需工作的比例不佳,通常可能无法实施。

答案 1 :(得分:4)

实施 - &gt; *需要解决完美的转发问题:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm

operator-&gt; *必须返回一个可调用对象,该对象具有与指向成员对象相同的参数列表,正确处理const-,volatile和引用类型。然后它必须使用特殊的魔力来处理默认参数。这很难,容易出错,无法解决并且占用太多的编译时间,并且由于指向成员的指针是C ++的一个相对边缘流行的特性,因此它们通常被排除在智能指针实现之外。

答案 2 :(得分:0)

我可能错了,但我认为没有办法将operator->*重载为指向成员函数的指针。这是因为p->*memfun虽然作为将其视为可调用对象的表达式的一部分有效,但它本身不是有效表达式,并且没有类型。因此,运营商无法返回有效类型。

以下内容适用于指向成员的指针,但尝试将其用于指向成员指针的函数会产生错误,“无效使用非静态成员函数”,使用GCC和内部函数MSVC编译错误。

template <class CLASS, typename MEMBER>
MEMBER& operator->*(std::auto_ptr<CLASS>& p, MEMBER CLASS::*m)
{
    return (*p).*m;
}
编辑:正如Georg的回答所指出的那样,你可以使用boost::bind或者类似的方法为成员函数创建一组重载,直到固定的最大参数数量,但是仍然没有办法让所有人都重载运算符可能的成员职能。