Overloading operator ->* for smart pointers I am implementing a smart pointer class template and I want to overload operator -&gt;* (even if it’s rarely done). I came across Scott Meyer’s article Implementing operator ->* for Smart Pointers. The article is from 1999 so I decided to try to adapt the code for C++ 14 (using parameter packs and perfect forwarding) and to improve it by adding support for pointer to data member—Meyer’s implementation only supports pointer to member functions—(which is the first of the two remaining problems of Meyer’s implementation that are listed at the section “Loose Ends” of his article and that he gives the reader as exercises to solve).

I ended up with the following code that seems to work quite fine. Now I have two questions:


Is there anything that could be improved in my code?
How to solve the second remaining problem listed at the section “Loose Ends” of Meyer’s article? (“You can’t use user-defined pointers-to-members. If someone has overloaded operator ->* to take objects that act like member pointers, you may want to support such ‘smart pointers to members’ in your smart pointer class. Unfortunately, you need traits classes to get the result type of such overloaded operator ->*.”)


Here is the code:

#include&lt;iostream&gt;

template&lt;typename T&gt;
struct Member_function_type_traits { };

template&lt;typename O, typename... A, typename R&gt;
struct Member_function_type_traits&lt;R (O::*)(A...)&gt; {
  typedef O Object_T;
  typedef R Return_T;
};

template&lt;typename O, typename... A, typename R&gt;
struct Member_function_type_traits&lt;R (O::*)(A...) const&gt; {
  typedef O Object_T;
  typedef R Return_T;
};

template&lt;typename O, typename... A, typename R&gt;
struct Member_function_type_traits&lt;R (O::*)(A...) volatile&gt; {
  typedef O Object_T;
  typedef R Return_T;
};

template&lt;typename O, typename... A, typename R&gt;
struct Member_function_type_traits&lt;R (O::*)(A...) const volatile&gt; {
  typedef O Object_T;
  typedef R Return_T;
};

template&lt;typename T&gt;
class Pending_member_function_call {
  typedef typename Member_function_type_traits&lt;T&gt;::Object_T Object_T;
  typedef typename Member_function_type_traits&lt;T&gt;::Return_T Return_T;
  std::pair&lt;Object_T*, T&gt; operands;  
  public:
    Pending_member_function_call(std::pair&lt;Object_T*, T&gt; opr): operands{opr} { }
    template&lt;typename... U&gt;
    Return_T operator ()(U&amp;&amp;... args) {
      return (operands.first-&gt;*operands.second)(std::forward&lt;U&gt;(args)...);
  }
};

template&lt;typename T&gt;
class Smart_pointer {
  T* ptr;
  public:
    Smart_pointer(T* ptr): ptr{ptr} { }
    ~Smart_pointer() { delete ptr; }
    // …
    // operator -&gt;* overload for pointers to data member
    template&lt;typename U, typename V&gt;
    V operator -&gt;*(V U::* pdm) const {
      return ptr-&gt;*pdm;
    }
    // operator -&gt;* overload for pointers to member function
    template&lt;typename U&gt;
    Pending_member_function_call&lt;U&gt; operator -&gt;*(U pmf) const {
      return std::make_pair(ptr, pmf);
    }
};

struct A {
  int dm{5};
  int mf(int x) { return 2 * x; }
};

int main() {
  Smart_pointer&lt;A&gt; p{new A};
  auto pdm = &amp;A::dm;
  auto pmf = &amp;A::mf;
  std::cout &lt;&lt; "A::dm called: " &lt;&lt; p-&gt;*pdm &lt;&lt; '\n';
  std::cout &lt;&lt; "A::mf called: " &lt;&lt; (p-&gt;*pmf)(8) &lt;&lt; '\n';
  return 0;
}
Is there anything that could be improved in my code?


I think you can accomplish the same thing in much less code with just a lambda:

template &lt;class U&gt;
auto operator-&gt;*(U pmf) const {
    return [=](auto&amp;&amp;... args){
        return (ptr-&gt;*pmf)(std::forward&lt;decltype(args)&gt;(args)...);
    };
}


Could have a static_assert on std::is_member_pointer for extra safety.


  How to solve the second remaining problem listed at the section “Loose Ends” of Meyer’s article?


I believe the lambda solves this problem as well. 



Also you could consider const propagation. If the Smart_pointer is const, do you really want to allow calling non-const member functions? I don't know. If you decide you don't, you should provde both a const and non-const overload and forward to a helper:

template &lt;class U&gt;
auto operator-&gt;*(U pmf) {
    return pending_mem_fun(ptr, pmf);
}

template &lt;class U&gt;
auto operator-&gt;*(U pmf) const {
    return pending_mem_fun(const_cast&lt;T const*&gt;(ptr), pmf);
}


where pending_mem_fun doesn't actually have to be a member function.