为什么std :: shared_ptr没有operator->*
?
使用可变参数模板看起来很容易。
有关详细信息,请参阅this paper。
编辑:这似乎是:About shared_ptr and pointer to member operator `->*` and `std::bind`
的潜在副本答案 0 :(得分:4)
这可以在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)...);
};
}
添加SFINAE可选。注意上面的完美前锋,这是不完美的。它还支持奇怪的&#34;方法&#34;类型到某个exten,只要它们产生一些operator()
并且没有其他重要性。
由于完美转发的不完善,这仍然是不完美的,所以这可能是一个理由让它单独并强制.get()->*
。使用lambda而不是类也存在一些细微的缺陷,但这些可以修复。
克隆界面的解决方案也有缺陷(它们可以移动两次而不是一次,或暗示指数级的重载)。
我们可以在不修改->*
的情况下注入上述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)...);
};
}
}
然后using notstd::operator->*
将其考虑在内。有趣的是,->*
不一定是类的非静态成员,因为它与许多亲戚(例如->
和[]
)不同,可以使用它。
我为unique_ptr
添加了类似的内容,因为为什么不呢。
一个替代选项会将shared_ptr
存储在返回的lambda中:它会增加看起来像低级别操作的开销,所以我没有这样做,而且在unique_ptr
上它会被建议,如果有趣的话。
现在所有这些都很好,但没有回答这个问题。
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);
}
使用宏(如...
)或样板代码复制模拟boost
。这不是完美的(每个arg的两个副本而不是一个?我想我们可以用T
args替换T const&
args来修复它,但这很难。
相比之下,在C ++ 11中很容易。但是std shared ptr是与C ++ 11一起设计的,它的前身是在它之前设计的。所以对于前体来说,添加->*
会给很少的回报带来很多痛苦和困难,而C ++ 11共享ptr就是根据这些来编写的。
然而,这部分只是一个意见或一个故事。
答案 1 :(得分:2)
如果您需要,可以自己添加。 operator ->*
是ordinary binary operator,与operator +
一样,does not need成为会员。
这是一个稍微更通用的版本,它会为实现->*
的任何内容添加operator ->
支持。
template< typename obj, typename ptm >
auto operator ->* ( obj && o, ptm && p )
-> decltype( o.operator -> () ->* p )
{ return o.operator -> () ->* p; }
(推断的返回类型不合适,因为它不提供SFINAE,然后模板可能会干扰其他重载。而且,是的,如果forward
ed rvalues,上面的实现会更好。最后,如果不使用递归模板,则无法捕获operator ->
shared_ptr
。)
至于为什么operator ->*
本身不提供它,指向成员的指针经常被遗忘。标准库的其他任何部分都没有{{1}},尽管它总是适用于迭代器等。 drill-down behavior库中的功能也不在标准库功能之前。 (提升通常有更多的花里胡哨。)