Improving pointer to member function ->* (very bad) syntax
Tags: cpp
Published: 2023-04-17 07:54:31

---
title: Improving pointer to member function ->* (very bad) syntax
published: true
description: Having to write the parethesis in the expression (ptrObj->*ptrToMethod)(args...) feels so weird, let's improve that
tags: cpp
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrhzi0m2vvfew6qj6tz8.jpg
---

## Article::Article
Not so long ago, I was bored, so I went to browse [cppreference](https://en.cppreference.com/w/). Yes I do that, I know it's weird but don't mock my special interest!     
Anyway, I chose to go to the [Function objets](https://en.cppreference.com/w/cpp/utility/functional) without any real motive, except maybe to see if [std::move_only_function](https://en.cppreference.com/w/cpp/utility/functional/move_only_function), added in [C++23](https://en.cppreference.com/w/cpp/23) was already documented in the website.    
It was there, I also saw [std::function](https://en.cppreference.com/w/cpp/utility/functional/function) obviously, but before I scrolled down to see [std::bind](https://en.cppreference.com/w/cpp/utility/functional/bind), I stumbled upon one class I didn't recall, it's not even new, it was added in [C++11](https://en.cppreference.com/w/cpp/11). I'm talking about [std::mem_fn](https://en.cppreference.com/w/cpp/utility/functional/mem_fn).

What is it? Well, it's pretty simple, it's a function to create a wrapper around a pointer to method, instead of writing:
```C++
#include <iostream>

struct Foo
{
    void hi()
    {
        std::cout << "Hi" << std::endl;
    }
};

int main()
{
    auto ptr_hi = &Foo::hi;

    // Use .*
    Foo foo;
    (foo.*ptr_hi)();

    // Use ->*
    auto* foo_ptr = &foo;
    (foo_ptr->*ptr_hi)();
}
```
[Compiler explorer link](https://godbolt.org/z/d3MMfPhhT)    
You can write:
```C++
#include <iostream>
#include <functional>

struct Foo
{
    void hi()
    {
        std::cout << "Hi" << std::endl;
    }
};

int main()
{
    auto wrapped_hi = std::mem_fn(&Foo::hi);
    Foo foo;
    wrapped_hi(foo); // Work with a value
    wrapped_hi(&foo); // Also work with a pointer
}
```
[Compiler explorer link](https://godbolt.org/z/Mo9qbTGss)

So, it is not very useful except in two situations:
* If you plan to use it with [std::bind](https://en.cppreference.com/w/cpp/utility/functional/bind) before C++ 14 ([because there is no reason to use it since C++14](https://stackoverflow.com/questions/17363003/why-use-stdbind-over-lambdas-in-c14)) or with [std::bind_front](https://en.cppreference.com/w/cpp/utility/functional/bind_front) since C++20.
* If you want to pass a member function to a STL algorithm. There is this [very good article](https://www.fluentcpp.com/2020/03/06/how-to-pass-class-member-functions-to-stl-algorithms/) talking about it.

I almost forgot, it also works with smart pointers without needing to call their `get()` member function. So you don't have to use the operator `->*`.   
But wait! [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) and [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr) don't have an overload for this operator! The syntax is so bad, so few people use it that they did not implement it. Like seriously, when is the last time you used it?

![Meme, me as Phineas saying to you as Ferb, I know what we are going to do today](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrhzi0m2vvfew6qj6tz8.jpg)

Today, we are going to fix the operator `->*` by making a new syntax work!

## The issue with the operator ->*

We could expect to be able to write something like that:
```C++
my_ptr->*my_ptr_on_method(my_args...);
```
instead of that we are forced to write this:
```C++
(my_ptr->*my_ptr_on_method)(my_args...);
```
The reason we have to put parenthesis around `my_ptr->*my_ptr_on_method` is that the operator `()` with the [precedence](https://en.cppreference.com/w/cpp/language/operator_precedence) over the operator `->*` meaning that without the parenthesis, it would try to use the operator `()` of `my_ptr_on_method` first and it won't work.

Yes this is something very minor, but it is still frustrating and I can fix it!

## Idea
The idea will be very similar with what I did in [this article]() where I simulate the [unified call syntax](https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax).

The first part is to implement a wrapper around the pointer to member function. This wrapper will have the operator `()` overloaded and it will be able to take the same arguments as the member function it wraps, and it will return another object that I will call the _proxy_. 

This proxy is an object that will store the argument and the wrapped member function. It will also be able, if it is provided with an object corresponding to the wrapped member function, to make the actual call.

The last part is the overload of the operator `->*` that will prove the proxy with the object.

Here what it can looks like in pseudo code:
```C++

struct Proxy
{
    Proxy(member_function, args...);

    auto execute(Foo f)
    {
        (f->*member_function)(args...);
    }

    // Stored information
    args...;
    member_function;
};

struct Wrapper
{
    Wrapper(member_function);

    Proxy operator()(args...)
    {
        return Proxy(member_function, args...);
    }

    member_function;
};

auto operator->*(Foo f, Proxy p)
{
    return p.execute(f);
}

// Usage
auto wrapper = &Foo::print;
Foo foo;
foo->*wrapper("hi");

```

## Why not the operator `.*`?
Because it can't be overloaded.


## Implementation
First, we need the wrapper and it must be constructed from a member function:
```C++
template <typename MF>
class Wrapper
{
	private:
		using C = helper::ClassType<MF>;

	public:
		Wrapper(MF member_function):
			_member_function(member_function)
		{}

	private:
		MF _member_function;
};
```
That's nice, but could be better.

![Meme with the template Wonder woman guy saying that template are nice, but it could be better with concepts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymzew8zvh3j9m3el7a1a.jpg)

Let's add a [concept](https://en.cppreference.com/w/cpp/language/constraints) to check that the template argument is indeed a member function:
```C++
template <typename MF>
concept MemberFunction = std::is_member_function_pointer_v<MF>;
```
and then use it by replacing the keyword `typename` by `MemberFunction`:
```C++
template <MemberFunction MF>
class Wrapper
{
	private:
		using C = helper::ClassType<MF>;

	public:
		Wrapper(MF member_function):
			_member_function(member_function)
		{}

	private:
		MF _member_function;
};
```

Now we need to overload the operator `()` to return the proxy. It must take the arguments of the member function as parameter:

```C++
template <typename... Args>
void operator()(Args&&... args)
{
	
}
```

It must also return the proxy, but we haven't defined it yet! The simplest way to implement it is to use a lambda function, and take the arguments by capturing them in its scope:

```C++
template <typename... Args>
auto operator()(Args&&... args)
{
	// [&] means it takes everything from the current scope by reference
	// It will takes 'args...' and also 'this'
	return [&]() {  };
}
```
If you are following, you remember that the Proxy must be able to use the member function if provided with the right object, so let's add an argument for our lambda:
```C++
// Note that I use a template argument here to be able to use a forwarding reference
[&]<typename T>(T&& t) {  };
```
And now call the member function:
```
// std::forward<Args>(args)... may seem barbaric but it just means that we forward the argument
// With the exact same type as we got them
[&]<typename T>(T&& t) { return (t.*_member_function)(std::forward<Args>(args)...); };
```

The last thing to do for the wrapper is to add a concept to be able to check that the arguments provided corresponds so when it fails instead of having 3 pages of unreadable errors, we get only 20 lines.

Here's the concept:
```C++
template <typename T, typename MF, typename... Args>
concept MemberFunctionArgs = 
	requires(T&& t, MF mf, Args&&... args)
	{
		(t.*mf)(std::forward<Args>(args)...);
	};
```
Basically, the content is the same as the lambda and it returns true if this is possible.

With this concept added, the wrapper looks like that:
```C++
template <typename MF>
concept MemberFunction = std::is_member_function_pointer_v<MF>;

template <typename T, typename MF, typename... Args>
concept MemberFunctionArgs = 
	requires(T&& t, MF mf, Args&&... args)
	{
		(t.*mf)(std::forward<Args>(args)...);
	};


namespace helper
{

template <typename C, typename R, typename... Args>
struct DeduceClassTypeFromMemberFunction
{
	using Class = C;

	DeduceClassTypeFromMemberFunction(R (C::*)(Args...)){}
};

template <MemberFunction MF>
using ClassType = typename decltype(DeduceClassTypeFromMemberFunction(std::declval<MF>()))::Class;

} // namespace helper


template <MemberFunction MF>
class Wrapper
{
	private:
		using C = helper::ClassType<MF>;

	public:
		Wrapper(MF member_function):
			_member_function(member_function)
		{}

template <typename... Args>
auto operator()(Args&&... args) requires MemberFunctionArgs<C, MF, Args...>
{
	return [&]<typename T>(T&& t) { return (t.*_member_function)(std::forward<Args>(args)...); };
}

	private:
		MF _member_function;
};
```

The next step is to overload the operator `->*` and it is that simple:
```C++
template <typename T, typename Proxy>
constexpr auto operator->*(T&& t, Proxy&& p)
{
	return p(std::forward<T>(t));
}
```
But with a concept to check that `p(std::forward<T>(t))` is possible, it is better:
```C++
template <typename T, std::invocable<T> Proxy>
constexpr auto operator->*(T&& t, Proxy&& p)
{
	return p(std::forward<T>(t));
}
```

## Why object instead of pointers?
Because it is only possible to overload operators for objects, not pointers. So we would say that we are more fixing the operator `.*` using the `->*` in this particular case and that's why the overload of the operator `->*` takes a forwarding reference `T&&` and not a pointer (`T*`).

You can find the whole code source on github [here](https://github.com/Baduit/Cider).

## Article::~Article
Now it is possible to write that:
```C++
using cider::operator->*;
using cider::Wrapper;

struct Foo
{
	void bar(int a, int b)
	{
		std::cout << (a + b) << std::endl;
	};
};

auto wrapped = Wrapper(&Foo::bar);
Foo foo;
foo->*wrapped(1, 1);
```

I don't really expect this to be used in a real-world project, because this is an edge case usage and it adds some complexity for only a little gain. My point was to show that C++ is customizable, and it is not that hard to play with C++ syntax, it just needs some key concepts and some creativity. Also, the result is not necessarily ugly even if it may still seem complicated if you are not a bit familiar with templates.

## Sources
* [https://stackoverflow.com/questions/17363003/why-use-stdbind-over-lambdas-in-c14](https://stackoverflow.com/questions/17363003/why-use-stdbind-over-lambdas-in-c14)
* [https://stackoverflow.com/questions/62807743/why-use-stdbind-front-over-lambdas-in-c20](https://stackoverflow.com/questions/62807743/why-use-stdbind-front-over-lambdas-in-c20)
* [https://en.cppreference.com/w/cpp/utility/functional/mem_fn](https://en.cppreference.com/w/cpp/utility/functional/mem_fn)
* [https://en.cppreference.com/w/cpp/utility/functional/bind](https://en.cppreference.com/w/cpp/utility/functional/bind)
* [https://en.cppreference.com/w/cpp/utility/functional/bind_front](https://en.cppreference.com/w/cpp/utility/functional/bind_front)
* [https://www.fluentcpp.com/2020/03/06/how-to-pass-class-member-functions-to-stl-algorithms/](https://www.fluentcpp.com/2020/03/06/how-to-pass-class-member-functions-to-stl-algorithms/)