简体   繁体   English

为什么std :: shared_ptr没有运算符 - > *?

[英]Why doesn't std::shared_ptr have operator->*?

Why doesn't std::shared_ptr have operator->* ? 为什么std :: shared_ptr没有operator->*

An implementation would seem easy using variadic templates. 使用可变参数模板看起来很容易。

See this paper for more info. 有关详细信息,请参阅此文章

Edit: this seems like a potential duplicate of: About shared_ptr and pointer to member operator `->*` and `std::bind` 编辑:这似乎是一个潜在的重复: 关于shared_ptr和指向成员运算符的指针` - > *`和`std :: bind`

This could be added to std::shared_ptr after C++14 instead of the complex code you linked: 这可以在C ++ 14之后添加到std::shared_ptr而不是你链接的复杂代码:

template<class Method>
auto operator->*(Method&& method){
  return [t=get(),m=std::forward<Method>(method)](auto&&args){
    return (t->*m)(std::forward<decltype(args)>(args)...);
  };
}

adding SFINAE optional. 添加SFINAE可选。 Note the above perfect forwards, which is imperfect. 注意上面的完美前锋,这是不完美的。 It also supports strange "method" types to a certain exten, so long as they produce somethung with an operator() and nothing else of importance. 它还为某个exten支持奇怪的“方法”类型,只要它们使用operator()生成somethung而没有其他重要的东西。

This is still imperfect due to imperfections in perfect forwarding, so that might be a reason to leave it alone and force .get()->* instead. 由于完美转发的不完善,这仍然是不完美的,因此这可能是一个单独使用并强制使用.get()->*的理由。 There are also some minor imperfections from the use of a lambda instead of a class, but those could be fixed. 使用lambda而不是类也存在一些细微的缺陷,但这些可以修复。

Solutions that clone the interface also have flaws (they can move twice instead of once, or imply an exponential number of overloads). 克隆接口的解决方案也存在缺陷(它们可以移动两次而不是一次,或者意味着指数级的重载)。

Amusingly we can inject the above ->* without modifying std : 有趣的是我们可以注入上面的->*而不需要修改std

namespace notstd{
  template<class...Ts, class Method>
  auto operator->*(std::shared_ptr<Ts...> const& p, Method&& method){
    return [t=p.get(),m=std::forward<Method>(method)](auto&&args){
      return (t->*m)(std::forward<decltype(args)>(args)...);
    };
  }
  template<class...Ts, class Method>
  auto operator->*(std::unique_ptr<Ts...> const& p, Method&& method){
    return [t=p.get(),m=std::forward<Method>(method)](auto&&args){
      return (t->*m)(std::forward<decltype(args)>(args)...);
    };
  }
}

then using notstd::operator->* brings it into consideration. 然后using notstd::operator->*将其考虑在内。 Amusingly, ->* need not be a non-static member of a class for it to be used unlike many of its relatives (like -> and [] ). 有趣的是, ->*不一定是类的非静态成员,因为它不像它的许多亲戚那样被使用(比如->[] )。

I included a similar one for unique_ptr , because why not. 我为unique_ptr包含了一个类似的,因为为什么不呢。

An alternative option would store the shared_ptr within the lambda returned: it adds overhead in what looks like a low level operation, so I did not do it, and on unique_ptr it would be ill advised, if funny. 另一种选择是将shared_ptr存储在返回的lambda中:它增加了看起来像低级别操作的开销,所以我没有这样做,而对于unique_ptr ,如果有趣的话,这将是不明智的。

Now all the above is well and good, but doesn't answer the question. 现在以上所有都很好,但没有回答这个问题。

A C++03 shared ptr (say, boost shared ptr) could have added: 一个C ++ 03共享ptr(比如,boost shared ptr)可能已添加:

template<class T, class R, class...Args>
struct mem_fun_invoke; // details, exposes `R operator()(Args...)const`
template<class T, class D, class R, class...Args>
mem_fun_invoke<T,R,Args...>
operator->*(std::shared_ptr<Ts...> const& p, R(T::*Method)(Args...)){
  return mem_fun_invoke<T,R,Args...>(p.get(), Method);
}

with ... emulated using macros (like in boost ) or boilerplate code replication. with ...使用宏模拟(如在boost )或样板代码复制。 This wouldn't be perfect (two copies of each arg made instead of one? I guess we could replace T args with T const& args to fix that), but it would be hard. 这不是完美的(每个arg的两个副本而不是一个?我想我们可以用T const& args替换T args来修复它),但这很难。

In comparison, in C++11 it is easy. 相比之下,在C ++ 11中很容易。 But std shared ptr was designed along with C++11, and its precursors where designed before it. 但是std shared ptr是与C ++ 11一起设计的,它的前身是在它之前设计的。 So to the precursors, adding ->* would be a lot of pain and boilerplate for little return, and C++11 shared ptr was written based off those. 所以对于前体来说,添加->*会带来很多痛苦和样板回报,并且C ++ 11共享ptr是基于这些而编写的。

This part, however, is just an opinion or a just-so-story. 然而,这部分只是一个观点或一个故事。

If you want it, you can add it yourself. 如果您需要,可以自己添加。 operator ->* is an ordinary binary operator , and like operator + , it does not need to be a member. operator ->*是一个普通的二元运算符 ,和operator + ,它不需要是成员。

Here is a slightly more general version, which will add ->* support to anything implementing operator -> . 这是一个稍微更通用的版本,它将添加->*支持任何实现operator ->东西。

template< typename obj, typename ptm >
auto operator ->* ( obj && o, ptm && p )
-> decltype( o.operator -> () ->* p )
    { return o.operator -> () ->* p; }

(A deduced return type isn't appropriate because it doesn't provide SFINAE, and then the template could interfere with other overloads. And, yes, the above implementation would be better if it forward ed rvalues. Finally, the drill-down behavior of operator -> cannot be captured without the use of a recursive template.) (推导出的返回类型不合适,因为它不提供SFINAE,然后模板可能会干扰其他重载。并且,是的,如果它forward r值,上述实现会更好。最后,下钻行为 operator ->如果不使用递归模板,则无法捕获。)

As for why shared_ptr doesn't provide it natively, pointer-to-members are just often forgotten. 至于为什么shared_ptr本身不提供它,指向成员的指针经常被遗忘。 No other part of the standard library has an operator ->* , although it would always have been appropriate for iterators and such. 标准库的其他任何部分都没有operator ->* ,尽管它总是适用于迭代器等。 Neither is the functionality in the Boost.SmartPtr library which preceded the standard library feature. Boost.SmartPtr库中的功能也不在标准库功能之前。 (Boost often has more bells and whistles.) (提升通常有更多的花里胡哨。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM