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

发布于 2024-09-10 11:11:57 字数 667 浏览 1 评论 0原文

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->*():

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

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

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

auto_ptr (shared_ptr as well) try to make their use as transparent as possible; that is, ideally, you should not be able to tell a difference whether you're using an auto_ptr or a real pointer to an object. Consider:

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

When you try to invoke a member function through a pointer-to-member, there is a difference, as auto_ptr obviously doesn't implement op->*():

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

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

Why is there no support for op->*() in auto_ptr and how would one implement it (I've experimented for some time, but ultimately gave up).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ゝ偶尔ゞ 2024-09-17 11:11:57

正如路德指出的那样,实施起来并不简单——但它是可能的。

您必须

  1. 使用模板,以便可以推导 operator->* 的参数类型,
  2. 使用成员函数指针的重载来处理可能的限定符和多个函数参数,
  3. 返回一个 callabe 对象,即:
    • 绑定到智能指针指向的实例
    • 实现一个operator(),其签名与成员函数相同

暂时忽略限定符,下面是它的基本外观(使用 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)

..由于所需的工作与此功能所带来的收益之间的比例不佳,它通常可能不会被实现。

As Luther points out its non-trivial to implement - but it is possible.

You have to

  1. use templates so the type of the arguments to operator->* can be deduced
  2. take care of possible qualifiers and multiple function arities using overloads
  3. for member function pointers return a callabe object that is:
    • bound to the instance the smart pointer points to
    • implements an operator() with a signature equivalent to the member function

Ignoring qualifiers for the momement, here is how it could basically look (using C++0x to avoid manual repitition):

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

But in the end, why bother when we could just use functors that bind member pointers in the first place.

While i can't be sure about it, if you combine the knowledge that

  • the implementation is non-trivial
  • there is an easy alternative that works just as well ((*p).*m)

... its probably usually not implemented due to a bad ratio of the work-needed to the gains resulting from this feature.

屋檐 2024-09-17 11:11:57

实现 ->* 需要解决完美转发问题:

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

运算符->* 必须返回一个具有相同值的可调用对象参数列表作为指向成员对象的指针,正确处理常量、易失性和引用类型。然后它必须使用特殊的魔力来处理默认参数。这是困难的、容易出错、无法解决的,并且会消耗太多的编译时间,而且由于指向成员的指针是 C++ 中相对不太受欢迎的功能,因此它们通常被排除在智能指针实现之外。

implementing ->* would require to solve the perfect forwarding problem:

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

operator->* would have to return a callable object with the same parameter list as the pointer-to-member object, correctly handling const-,volatileness and reference types. And then it would have to employ special magic powers to handle default parameters. This is difficult, error prone, unsolvable and eats too much compile time and since pointer-to-members are a comparably marginally popular feature of C++, they are generally left out of smart pointer implementations.

迷爱 2024-09-17 11:11:57

我可能是错的,但我认为没有办法为指向成员函数的指针重载 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 或类似的方法为成员函数创建一组重载,最多可达固定的最大参数数量,但仍然无法重载所有可能的成员函数的运算符。

I may be wrong, but I think there's no way to overload operator->* for a pointer-to-member-function. This is because p->*memfun, while valid as part of an expression that treats it as a callable object, isn't a valid expression in its own right, and doesn't have a type. There is therefore no valid type for the operator to return.

The following will work for a pointer-to-member, but trying to use it for a pointer-to-member-function gives an error, "invalid use of non-static member function", with GCC, and an internal compiler error with MSVC.

template <class CLASS, typename MEMBER>
MEMBER& operator->*(std::auto_ptr<CLASS>& p, MEMBER CLASS::*m)
{
    return (*p).*m;
}

EDIT: as Georg's answer points out, you can use boost::bind or similar to create a set of overloads for member functions up to a fixed maximum number of arguments, but there's still no way to overload the operator for all possible member functions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文