【问题标题】:Pointer-like classes and the ->* operator类指针类和 ->* 运算符
【发布时间】:2015-08-06 09:29:54
【问题描述】:

我最近遇到了需要将指向成员的指针应用于由迭代器指定的对象。我已经尝试过自然语法:

ite->*ptr = 42;

令我沮丧的是,它没有编译。迭代器不会重载operator->*,但更令人惊讶的是,智能指针也不会。我需要求助于以下笨拙:

(*ite).*ptr = 42;

实验(请参阅下面的实时示例)表明,对于指向成员的指针和指向成员函数的指针,这种语法似乎对于自定义类是可以实现的,至少从 C++14 开始。

因此:

  • 标准类指针类不会重载operator->* 是否有原因,还是只是疏忽?
  • 在定义自己的类指针类时,我应该重载operator->*,还是同样的原因也适用于我?

Live example -- 什么可以编译,什么不可以,以及自定义类的概念验证。

【问题讨论】:

  • @Galik 我的意思是指向成员的指针,而不是普通成员。看看here.
  • stackoverflow.com/questions/14106975/… 那里提出了一些好的观点
  • 另见stackoverflow.com/questions/17696664/…——虽然这更多是关于指向成员函数的指针而不是指向数据成员的指针。
  • @Hcorg 非常感谢你,这很有启发性——成员函数确实很痛苦。但是它们在 C++14 中看起来不错(我更新了示例)。
  • @ecatmur 它确实带来了一些我没有意识到的真正有趣的东西:可以将operator->* 定义为非成员。除非这样的运算符是一个糟糕的主意,否则它可以“热补丁”到标准类上。很好,谢谢!

标签: c++ iterator operator-overloading c++14 smart-pointers


【解决方案1】:

您可以使用免费函数重载->*。它不必是成员。

template <typename P,
          typename T,
          typename M>
M& operator->* (P smartptr, M T::*ptrmem)
{
    return (*smartptr).*ptrmem;
}

现在所有定义了一元 operator* 的东西(迭代器、智能指针等)也可以使用 -&gt;*。您可能希望以更可控的方式进行操作,即分别为已知的迭代器、已知的智能指针等定义它。

由于显而易见的原因,这不适用于成员函数。对于这种情况,需要专门化/重载并返回绑定的std::function

template <typename P,
          typename T,
          typename M,
          typename ... Arg>
std::function<M(Arg&&...)> 
operator->* (P smartptr, M (T::*ptrmem)(Arg... args))
{
    return [smartptr,ptrmem](Arg&&... args) -> M 
      { return ((*smartptr).*ptrmem)(std::forward<Arg>(args)...); };
}

【讨论】:

    【解决方案2】:

    这是你想做的((&amp;*ite)-&gt;*ptr) = 42; 吗?

    【讨论】:

    • 对不起。是((&amp;*ite)-&gt;*ptr) = 42; 吗?
    • 这可行,但特别是我不想使用的解决方法。请注意,这个问题不是要解决的实际问题,而是为什么不能用自然语法来解决,即使技术上可以实现这种语法。
    • 实际上有一种自然语法ite-&gt;*ptr = 42; 调用迭代器类的成员。如果重载运算符,则不能使用它来调用迭代器的成员。这就是为什么它不是。
    • 但是迭代器不是指针,所以不重载ite-&gt;*ptr是不正确的,ite.*ptr是。无论如何,多个重载可以区分属于迭代器的成员和属于其指针对象的成员。
    • 另外,我没有注意到您还没有评论所需的声誉,对此感到抱歉。
    猜你喜欢
    • 2013-07-16
    • 2017-09-04
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    • 2013-05-26
    • 2015-10-21
    • 2020-12-24
    • 1970-01-01
    相关资源
    最近更新 更多