I propose the inclusion of a function object (somewhat similar to the deprecated ptr_fun) that looks something like:
template<auto f>
requires is_pointer_v<decltype(f)> &&
is_function_v<remove_pointer_t<decltype(f)>>
struct func_ptr {
template<typename... Args>
decltype(auto) operator()(Args&&... args) noexcept(noexcept(f(forward<Args>(args)...))) {
return f(forward<Args>(args)...);
}
};
The main difference with ptr_fun being that the function pointer is part of the type.
Motivation
The main motivating example is a unique_ptr that needs to call a custom deleter function. Currently (assuming you don't want to write some per-deleter boilerplate), you'd need to do something like:
std::unique_ptr<MyType, decltype(&myDeleter)> ptr(something, myDeleter);
This presents a few issues:
- You don't get to use the default constructor for unique_ptr. Not a big deal but it can be inconvenient.
- You aren't actually declaring a unique_ptr that calls the myDeleter function, you're declaring a unique_ptr that calls a function pointer with the same signature as the myDeleter function. If the object gets passed around a bit, the compiler won't be able to inline the deletion and you'll probably be left with an indirect call.
- For the same reason as issue 2, storing the function pointer doubles the size of the object.
I believe that:
std::unique_ptr<MyType, std::func_ptr<myDeleter>> ptr;
solves all of those issues.