Defining interfaces for functions that accept only functions

Define (f + g) as the mean (f + g) (x): = f (x) + g (x). The addition of a conventional matrix is ​​consistent with this definition.

Here is a naive implementation

template<typename Funcf, typename Funcg> auto operator+(Funcf f, Funcg g){ return [f, g](auto x){return f(x) + g(x);}; } 

This fails because operator+ only consumes user-defined types. The next attempt gives

 template<typename R, typename I> auto operator+(std::function<R(I)> f, std::function<R(I)> g){ return [f, g](auto x){return f(x) + g(x);}; } 

This works, and it does not interfere with the namespace. However, it robs indirectness, and the call site is ugly auto added = std::function<int(int)>{f} + std::function<int(int)>{g}; .

If the first operator+ was enabled (or was renamed to add), the call site would be better and functions would be built-in. But he is trying to match everything that seems fragile.

Is it possible to define a template interface that indicates that the inputs are functions, still embeds them, but not pollute the namespace with an overly common name?

In other words, is there a temporary version of std::function to compile with a more convenient site? I strongly suspect the answer is no. And if the answer is no, is there a compromise between the two extremes mentioned above?

Or the third option, I think about it wrong? How would you model (f + g) in C ++?

+1
source share
1 answer

Operators work only for custom types. Then let your function be!

We can define a type that is basically lambda, but with a user defined user name:

 template<typename F> struct addable_lambda_impl : F { template<typename T> addable_lambda_impl(T f) : F{std::move(f)} {} using F::operator(); }; template<typename F> addable_lambda_impl<F> addable_lambda(F f) { return addable_lambda_impl<F>{std::move(f)}; } 

This is a class that extends any type and will use its operator() .

Now you can use the addable_lambda function:

 auto lambda = addable_lambda([](){}); 

Implementing your statement is simpler:

 template<typename F, typename G> auto operator+(addable_lambda_impl<F> f, addable_lambda_impl<G> g){ return addable_lambda([f, g](auto x){ return f(x) + g(x); }); } 

It's not perfect, but a little less ugly. In addition, you do not experience the overhead that std::function adds.

+1
source

Source: https://habr.com/ru/post/1011489/


All Articles