Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer-like classes and the ->* operator

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.

like image 329
Quentin Avatar asked Aug 06 '15 09:08

Quentin


People also ask

What are the operators of pointer?

C++ provides two pointer operators, which are Address of Operator (&) and Indirection Operator (*). A pointer is a variable that contains the address of another variable or you can say that a variable that contains the address of another variable is said to "point to" the other variable.

What is a pointer class?

A pointer to a C++ class is done exactly the same way as a pointer to a structure and to access members of a pointer to a class you use the member access operator -> operator, just as you do with pointers to structures. Also as with all pointers, you must initialize the pointer before using it.

What is the purpose of * and & operator in pointer?

The Address of Operator & The & is a unary operator that returns the memory address of its operand.

Which operator is called as pointer to member operator?

* or ->* pointer-to-member operators is an object or function of the type specified in the declaration of the pointer to member. So, in the preceding example, the result of the expression ADerived.


1 Answers

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)...); };
}
like image 59
n. 1.8e9-where's-my-share m. Avatar answered Nov 21 '22 11:11

n. 1.8e9-where's-my-share m.