I've recently come across the need to apply a pointer-to-member to the object designated by an iterator. I've tried the natural syntax :
ite->*ptr = 42;
To my dismay, it didn't compile. Iterators don't overload operator->*
, but more surprisingly neither do smart pointers. I needed to resort to the following clunkiness :
(*ite).*ptr = 42;
Experimenting (see the live example below) has shown that such a syntax seems to be achievable for custom classes, for both pointers-to-members and pointers-to-member-functions, at least since C++14.
Thus :
- Is there a reason the standard pointer-like classes don't overload
operator->*
, or is it just an oversight ? - Should I overload
operator->*
when defining my own pointer-like classes, or does this same reason apply to me ?
Live example -- what compiles, what doesn't, and a proof-of-concept for a custom class.
You can overload ->*
with a free function. It doesn't have to be a member.
template <typename P,
typename T,
typename M>
M& operator->* (P smartptr, M T::*ptrmem)
{
return (*smartptr).*ptrmem;
}
Now everything that has unary operator*
defined (iterators, smart pointers, whatever) can also use ->*
. You may want to do it in a bit more controlled fashion, i.e. define it for known iterators, known smart pointers etc. separately.
This will not work for member functions for obvious reasons. One would need to specialize/overload for this case and return a bound std::function
instead:
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)...); };
}
Is that what you want to do ((&*ite)->*ptr) = 42;
?
来源:https://stackoverflow.com/questions/31851987/pointer-like-classes-and-the-operator