Most Terse and Reusable Way of Wrapping Template or Overloaded Functions in Function Objects

Most terse and reusable way of wrapping template or overloaded functions in function objects

You can create a macro like

#define FUNCTORIZE(func) [](auto&&... val) \
noexcept(noexcept(func(std::forward<decltype(val)>(val)...))) -> decltype(auto) \
{return func(std::forward<decltype(val)>(val)...);}

which will let you wrap any callable into a closure object. You would use it like

auto constexpr predObj = FUNCTORIZE(pred);

How to declare the template argument for an overloaded function

You can wrap the function in a lambda, or pass a function pointer after casting it to the type of the overload you want to call or explicitly specify the template parameter:

use_funct([](){ do_something (); });
use_funct(static_cast<void(*)()>(do_something));
use_funct<void()>(do_something);

Wrapping it in a lambda has the advantage, that it is possible to defer overload resolution to use_func. For example:

void do_something(int) {}

void do_something(double) {}

template<typename F> void use_funct(F funct) {
funct(1); // calls do_something(int)
funct(1.0); // calls do_something(double)
}

int main() {
use_funct([](auto x){ do_something (x); });
}

[...] possibly without referring to a function pointer?

I am not sure what you mean or why you want to avoid that. void() is the type of the function, not a function pointer. If you care about spelling out the type, you can use an alias:

using func_type = void();
use_funct<func_type>(do_something);

Does Boost (or another library) offer a way to lift the name of a constructor-less class into a function object that uses aggregate initialization?

If you want a function object that constructs an object of some type T given some parameters, even if T is an aggregate, that's not difficult to write in C++17:

template<typename T>
struct lifted_construct
{
template<typename ...Args>
T operator() (Args&& ...args)
{
if constexpr(std::is_aggregate_v<T>)
{
return T{std::forward<Args>(args)...};
}
else
{
return T(std::forward<Args>(args)...);
}
}
};

Of course, in C++20, you can use () syntax even for aggregates.

How to use std::max or std::min as function parameter

The following works:

void foo (std::function<double const&(double const&, double const&)>) {}
void foo2 (double const&(double const&, double const&)){}

int main () {
foo((double const&(*)(double const&, double const&))(std::max<double>));
foo2(std::max<double>);
}

Note that we always need to use std::max<double>.

In the call to foo, as it takes a std::function, theres no good way the compiler can work out which overloaded version of std::max to use and so you need to cast it to the correct type.

For the second one, as foo2 takes the raw function, it just works.

Note that I've explicitly use double const&, as the plain T versions (as in not having the const&) of std::max take an initialiser list and so there's no way to cast it to what you need.

So to get it working with the foo as written, you'll have to use a lambda or overload or wrapper of some sort.

So the simplest way would be to use the knowledge above of what does work, and add an overload:

void foo(double const&(*func)(double const&, double const&) )
{
foo([&func](double a, double b){return func(a, b);});
}

and then foo(std::max<double>); will work



Related Topics



Leave a reply



Submit