C++: Function Composition

Bjarne-stroustrup
 

Create a function, compose, whose two arguments f and g, are both functions with one argument. The result of compose is to be a function of one argument, (lets call the argument x), which works like applying function f to the result of applying function g to x, i.e,

compose(f, g) (x) = f(g(x))

Reference: Function composition

Hint: In some languages, implementing compose correctly requires creating a closure.

#include <functional>
#include <cmath>
#include <iostream>

// functor class to be returned by compose function
template <class Fun1, class Fun2>
class compose_functor :
public std::unary_function<typename Fun2::argument_type,
typename Fun1::result_type>
{
protected:
	Fun1 f;
	Fun2 g;

public:
	compose_functor(const Fun1& _f, const Fun2& _g)
	: f(_f), g(_g) { }

	typename Fun1::result_type
	operator()(const typename Fun2::argument_type& x) const
	{ return f(g(x)); }
};

// we wrap it in a function so the compiler infers the template arguments
// whereas if we used the class directly we would have to specify them explicitly
template <class Fun1, class Fun2>
inline compose_functor<Fun1, Fun2>
compose(const Fun1& f, const Fun2& g)
{ return compose_functor<Fun1,Fun2>(f, g); }

int main() {
	std::cout << compose(std::ptr_fun(::sin), std::ptr_fun(::asin))(0.5) << std::endl;

	return 0;
}

composing std::function

#include <iostream>
#include <functional>
#include <cmath>

template <typename A, typename B, typename C>
std::function<C(A)> compose(std::function<C(B)> f, std::function<B(A)> g) {
	return [f,g](A x) { return f(g(x)); };
}

int main() {
	std::function<double(double)> f = sin;
	std::function<double(double)> g = asin;
	std::cout << compose(f, g)(0.5) << std::endl;

	return 0;
}

This much simpler version uses decltype(auto).

#include <iostream>
#include <math.h>

template <class F, class G>
decltype(auto) compose(F&& f, G&& g)
{
	return [=](auto x) { return f(g(x)); };
}

int main() {
	std::cout << compose(sin, asin)(0.5) << "\n";
	return 0;
}

GCC’s C++ library has a built-in compose function

#include <iostream>
#include <cmath>
#include <ext/functional>

int main() {
	std::cout << __gnu_cxx::compose1(std::ptr_fun(::sin), std::ptr_fun(::asin))(0.5) << std::endl;

	return 0;
}

SOURCE

Content is available under GNU Free Documentation License 1.2.