为什么std::shared_ptr没有operator->*?
使用可变参数模板似乎很容易实现。
有关更多信息,请参见此论文。
编辑:这似乎是一个潜在的重复问题: 关于shared_ptr和指向成员运算符`->*`以及std::bind。
使用可变参数模板似乎很容易实现。
有关更多信息,请参见此论文。
编辑:这似乎是一个潜在的重复问题: 关于shared_ptr和指向成员运算符`->*`以及std::bind。
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可选项。请注意上面的完美转发并不完美。它也支持某些奇怪的“方法”类型,只要它们生成一个带有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)...);
};
}
}
notstd::operator->*
将其考虑在内。有趣的是,与许多相关的成员(如 ->
和 []
)不同,->*
不需要成为类的非静态成员才能使用。
我也为 unique_ptr
提供了类似的内容,因为何乐而不为呢。
另一种选择是将 shared_ptr
存储在返回的 lambda 中:这会增加看起来像低级操作的开销,因此我没有这样做,在 unique_ptr
上这样做是不明智的,尽管很有趣。
现在,上述所有内容都很好,但并没有回答问题。
C++03 shared 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);
}
...
是一种方法。这种方法可能并不完美(每个参数都需要复制两次?我猜我们可以用T const&
参数替换T
参数来解决这个问题),但是实现难度很大。->*
将需要大量的麻烦和样板文件,而基于这些前身编写了C++11 shared ptr。is_smart_ptr
特性。不确定使用示例会包括什么?将其注入到智能指针类中,然后执行(smart_ptr->*method_ptr)(arg1, arg2)
? - Yakk - Adam Nevraumontstd::shared_ptr
一起使用。 - Lightness Races in Orbitstd
的版本,因为为什么不呢。仍然没有示例,因为那需要大于4英寸的屏幕,或者麻烦在手机上安装编译器。嗯,我应该这样做。 - Yakk - Adam Nevraumontoperator ->*
是一个普通二元运算符,就像operator +
一样,它不需要成为一个成员。operator ->
的东西添加->*
支持。template< typename obj, typename ptm >
auto operator ->* ( obj && o, ptm && p )
-> decltype( o.operator -> () ->* p )
{ return o.operator -> () ->* p; }
forward
rvalues,上面的实现会更好。最后,operator ->
的下钻行为无法在没有使用递归模板的情况下捕获。
至于为什么shared_ptr
没有提供本地支持,指向成员的指针经常被遗忘。标准库中没有任何其他部分有operator ->*
,尽管对于迭代器等始终是合适的。这种功能也不在先前的标准库功能之前的Boost.SmartPtr库中。(Boost通常具有更多的功能。)->*
吗?这样会重复钻取吗?还是它不会将自身考虑在 ->*
调用中? - Yakk - Adam Nevraumont
std::shared_pointer
еҸҜд»ҘжҢҒжңүдёҖдёӘзұ»жҢҮй’ҲгҖӮеӣ жӯӨпјҢеҸҜд»ҘиҮӘ然ең°зј–еҶҷ(sp->*ptr_to_member)()
дҪңдёә(sp.get()->*ptr_to_member)()
зҡ„з®ҖеҶҷгҖӮе®һзҺ°иҝҷдёӘеҠҹиғҪдјҡзӣёеҪ“жЈҳжүӢгҖӮ - Igor Tandetnik