Related
I have such kind of code:
const auto temp = std::make_pair(std::make_pair(std::make_pair('Q', 1.2),
std::string("POWER")), 1);
std::cout << std::format("({}, {}, {}, {})\n", temp.first.first.first,
temp.first.first.second, temp.first.second, temp.second);
that obviously prints:
(Q, 1.2, POWER, 1)
I want to make it more readable and intuitive by converting "pair of pair and smth" to std::tuple:
const auto temp = std::make_pair(std::make_pair(std::make_pair('Q', 1.2),
std::string("POWER")), 1);
const auto tuple = PairsToTuple(temp);
std::cout << std::format("({}, {}, {}, {})\n", std::get<0>(tuple),
std::get<1>(tuple), std::get<2>(tuple), std::get<3>(tuple));
How can I do that?
You can recursively std::tuple_cat
template<typename First, typename Second>
auto flatten(std::pair<First, Second> pair) {
return std::tuple_cat(flatten(pair.first), flatten(pair.second));
}
template<typename... Types>
auto flatten(std::tuple<Types...> tup) {
return std::apply([](auto... args) { return std::tuple_cat(flatten(args)...);}, tup);
}
template<typename T>
auto flatten(T t) {
return std::tuple{ t };
}
See it on coliru
If you have C++20, we can generalise this to anything tuple-like with a concept:
template<typename T>
auto flatten(T&& t) {
if constexpr (tuple<std::remove_cvref_t<T>>) {
return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
return std::tuple_cat(flatten(get<Is>(std::forward<T>(t)))...);
}(std::make_index_sequence<std::tuple_size_v<std::remove_cvref_t<T>>>{});
} else {
return std::tuple{ std::forward<T>(t) };
}
}
See it on coliru
I'm wondering if there is an elegant solution for composing mathematical operators in C++. By operator, I mean something like the following:
template<class H>
class ApplyOp {
H h;
public:
ApplyOp(){}
ApplyOp(H h_i) : h(h_i) {}
template<class argtype>
double operator()(argtype f,double x){
return h(x)*f(x);
}
};
The above class makes use of a "helper function" h(x). For example,
struct Helper{
Helper(){}
double operator()(double x){return x*x;}
};
struct F{
F(){}
double operator()(double x){return exp(x);}
};
int main()
{
Helper h;
F f;
ApplyOp<Helper> A(h);
std::cout<<"A(f,2.0) = "<<A(f,2.0)<<std::endl; //Returns 2^2*exp(2) = 29.5562...
return 0;
}
Now, I would like to compose the operator twice or more times, i.e. compute A^2(f,2.0). In the above example, this would return h(x)*h(x)*f(x). Note that this is not function composition, i.e. I do not want to compute A(A(f,2.0),2.0). Rather, think in terms of computing powers of a matrix: if h(x) = M (a matrix), I want M*M*...*M*x.
I was able to use std::bind() to achieve my desired result for A^2 (but not higher powers!) as follows:
auto g = std::bind(&ApplyOp<Helper>::operator()<F>,&A,f,std::placeholders::_1);
With the resulting g, I can apply A^2(f,2.0) by simply calling A(g,2.0). With the above examples, this would return h(x)*h(x)*f(x) = x*x*x*x*exp(x)
How would I generalize this to iteratively applying the operator A N times? I really liked the answer posted here, but it doesn't quite work here. I tried doing nested std:binds but quickly got into deep compiler errors.
Any ideas?
Complete working example:
#include<iostream>
#include<math.h>
#include<functional> //For std::bind
template<class H>
class ApplyOp {
H h;
public:
ApplyOp(){}
ApplyOp(H h_i) : h(h_i) {}
template<class argtype>
double operator()(argtype f,double x){
return h(x)*f(x);
}
};
struct Helper{
Helper(){}
double operator()(double x){return x*x;}
};
struct F{
F(){}
double operator()(double x){return exp(x);}
};
int main()
{
Helper h;
F f;
ApplyOp<Helper> A(h);
std::cout<<"A(f,2.0) = "<<A(f,2.0)<<std::endl; //Returns 2^2*exp(2) = 29.5562...
auto g = std::bind(&ApplyOp<Helper>::operator()<F>,&A,f,std::placeholders::_1);
std::cout<<"A^2(f,2.0) = "<<A(g,2.0) <<std::endl; //Returns 2^4*exp(2) = 118.225...
return 0;
}
Try this, using template specialization
#include<iostream>
#include<math.h>
#include<functional> //For std::bind
template<class H>
class ApplyOp {
H h;
public:
ApplyOp(){}
ApplyOp(H h_i) : h(h_i) {}
template<class argtype>
double operator()(argtype f,double x){
return h(x)*f(x);
}
};
struct Helper{
Helper(){}
double operator()(double x){return x*x;}
};
struct F{
F(){}
double operator()(double x){return exp(x);}
};
// C++ doesn't permit recursive "partial specialization" in function
// So, make it a struct instead
template<typename T, typename U, typename W, int i>
struct Binder {
auto binder(U b, W c) {
// Recursively call it with subtracting i by one
return [&](T x){ return b(Binder<T, U, W, i-1>().binder(b, c), x); };
}
};
// Specialize this "struct", when i = 2
template<typename T, typename U, typename W>
struct Binder<T, U, W, 2> {
auto binder(U b, W c) {
return [&](T x){ return b(c, x); };
}
};
// Helper function to call this struct (this is our goal, function template not
// struct)
template<int i, typename T, typename U, typename W>
auto binder(U b, W d) {
return Binder<T, U, W, i>().binder(b, d);
}
int main()
{
Helper h;
F f;
ApplyOp<Helper> A(h);
std::cout<<"A(f,2.0) = "<<A(f,2.0)<<std::endl; //Returns 2^2*exp(2) = 29.5562...
// We don't need to give all the template parameters, C++ will infer the rest
auto g = binder<2, double>(A, f);
std::cout<<"A^2(f,2.0) = "<<A(g,2.0) <<std::endl; //Returns 2^4*exp(2) = 118.225...
auto g1 = binder<3, double>(A, f);
std::cout<<"A^3(f,2.0) = "<<A(g1,2.0) <<std::endl; //Returns 2^6*exp(2) = 472.2
auto g2 = binder<4, double>(A, f);
std::cout<<"A^4(f,2.0) = "<<A(g2,2.0) <<std::endl; //Returns 2^8*exp(2) = 1891.598...
return 0;
}
From what I could understand from you question, you are essentially trying to define
A^1(h, f, x) = h(x) * f(x)
A^n(h, f, x) = h(x) * A^(n-1)(h, f, x)
If you are open to using C++17, here is something you can build upon:
#include <iostream>
#include <math.h>
template <int N>
struct apply_n_helper {
template <typename H, typename F>
auto operator()(H h, F f, double x) const {
if constexpr(N == 0) {
return f(x);
} else {
return h(x) * apply_n_helper<N - 1>()(h, f, x);
}
}
};
template <int N>
constexpr auto apply_n = apply_n_helper<N>();
int main() {
auto sqr = [](double x) { return x * x; };
auto exp_ = [](double x) { return exp(x); };
std::cout << apply_n<100>(sqr, exp_, 2.0) << '\n';
std::cout << apply_n<200>(sqr, exp_, 2.0) << '\n';
return 0;
}
If C++17 is not an option, you can easily rewrite this to use template specializations instead of constexpr-if. I will leave this as an exercise. Here is a link to compiler explorer with this code: https://godbolt.org/z/5ZMw-W
EDIT Looking back at this question, I see that you are essentially trying to compute (h(x))^n * f(x) in a manner so that you don't have to actually do any looping at runtime and the generated code is equivalent to something like:
auto y = h(x);
auto result = y * y * ... * y * f(x)
\_____________/
n times
return result;
Another way of achieving this would be to have something as follows
#include <cmath>
#include <iostream>
template <size_t N, typename T>
T pow(const T& x) {
if constexpr(N == 0) {
return 1;
} else if (N == 1) {
return x;
} else {
return pow<N/2>(x) * pow<N - N/2>(x);
}
}
template <int N>
struct apply_n_helper {
template <typename H, typename F>
auto operator()(H h, F f, double x) const {
auto tmp = pow<N>(h(x));
return tmp * f(x);
}
};
template <int N>
constexpr auto apply_n = apply_n_helper<N>();
int main()
{
auto sqr = [](double x) { return x * x; };
auto exp_ = [](double x) { return exp(x); };
std::cout << apply_n<100>(sqr, exp_, 2.0) << '\n';
std::cout << apply_n<200>(sqr, exp_, 2.0) << '\n';
return 0;
}
Here, the usage of pow function is saving us from evaluating h(x) several times.
I mean you can use a other class:
template <typename T, std::size_t N>
struct Pow
{
Pow(T t) : t(t) {}
double operator()(double x) const
{
double res = 1.;
for (int i = 0; i != N; ++i) {
res *= t(x);
}
return res;
}
T t;
};
And use
ApplyOp<Pow<Helper, 2>> B(h); instead of ApplyOp<Helper> A(h);
Demo
So you want to be able to multiply functions. Well, that sounds good. Why not + and - and / while we are in there?
template<class F>
struct alg_fun;
template<class F>
alg_fun<F> make_alg_fun( F f );
template<class F>
struct alg_fun:F {
alg_fun(F f):F(std::move(f)){}
alg_fun(alg_fun const&)=default;
alg_fun(alg_fun &&)=default;
alg_fun& operator=(alg_fun const&)=default;
alg_fun& operator=(alg_fun &&)=default;
template<class G, class Op>
friend auto bin_op( alg_fun<F> f, alg_fun<G> g, Op op ) {
return make_alg_fun(
[f=std::move(f), g=std::move(g), op=std::move(op)](auto&&...args){
return op( f(decltype(args)(args)...), g(decltype(args)(args)...) );
}
);
}
template<class G>
friend auto operator+( alg_fun<F> f, alg_fun<G> g ) {
return bin_op( std::move(f), std::move(g), std::plus<>{} );
}
template<class G>
friend auto operator-( alg_fun<F> f, alg_fun<G> g ) {
return bin_op( std::move(f), std::move(g), std::minus<>{} );
}
template<class G>
friend auto operator*( alg_fun<F> f, alg_fun<G> g ) {
return bin_op( std::move(f), std::move(g),
std::multiplies<>{} );
}
template<class G>
friend auto operator/( alg_fun<F> f, alg_fun<G> g ) {
return bin_op( std::move(f), std::move(g),
std::divides<>{} );
}
template<class Rhs,
std::enable_if_t< std::is_convertible<alg_fun<Rhs>, F>{}, bool> = true
>
alg_fun( alg_fun<Rhs> rhs ):
F(std::move(rhs))
{}
// often doesn't compile:
template<class G>
alg_fun& operator-=( alg_fun<G> rhs )& {
*this = std::move(*this)-std::move(rhs);
return *this;
}
template<class G>
alg_fun& operator+=( alg_fun<G> rhs )& {
*this = std::move(*this)+std::move(rhs);
return *this;
}
template<class G>
alg_fun& operator*=( alg_fun<G> rhs )& {
*this = std::move(*this)*std::move(rhs);
return *this;
}
template<class G>
alg_fun& operator/=( alg_fun<G> rhs )& {
*this = std::move(*this)/std::move(rhs);
return *this;
}
};
template<class F>
alg_fun<F> make_alg_fun( F f ) { return {std::move(f)}; }
auto identity = make_alg_fun([](auto&& x){ return decltype(x)(x); });
template<class X>
auto always_return( X&& x ) {
return make_alg_fun([x=std::forward<X>(x)](auto&&... /* ignored */) {
return x;
});
}
I think that about does it.
auto square = identity*identity;
we can also have type-erased alg funs.
template<class Out, class...In>
using alg_map = alg_fun< std::function<Out(In...)> >;
these are the ones that support things like *=. alg_fun in general don't type erase enough to.
template<class Out, class... In>
alg_map<Out, In...> pow( alg_map<Out, In...> f, std::size_t n ) {
if (n==0) return always_return(Out(1));
auto r = f;
for (std::size_t i = 1; i < n; ++i) {
r *= f;
}
return r;
}
could be done more efficiently.
Test code:
auto add_3 = make_alg_fun( [](auto&& x){ return x+3; } );
std::cout << (square * add_3)(3) << "\n";; // Prints 54, aka 3*3 * (3+3)
alg_map<int, int> f = identity;
std::cout << pow(f, 10)(2) << "\n"; // prints 1024
Live example.
Here is a more efficient pow that works without type erasure:
inline auto raise(std::size_t n) {
return make_alg_fun([n](auto&&x)
-> std::decay_t<decltype(x)>
{
std::decay_t<decltype(x)> r = 1;
auto tmp = decltype(x)(x);
std::size_t bit = 0;
auto mask = n;
while(mask) {
if ( mask & (1<<bit))
r *= tmp;
mask = mask & ~(1<<bit);
tmp *= tmp;
++bit;
}
return r;
});
}
template<class F>
auto pow( alg_fun<F> f, std::size_t n ) {
return compose( raise(n), std::move(f) );
}
Live example. It uses a new function compose in alg_fun:
template<class G>
friend auto compose( alg_fun lhs, alg_fun<G> rhs ) {
return make_alg_fun( [lhs=std::move(lhs), rhs=std::move(rhs)](auto&&...args){
return lhs(rhs(decltype(args)(args)...));
});
}
which does compose(f,g)(x) := f(g(x))
Your code now literally becomes
alg_fun<Helper> h;
alg_fun<F> f;
auto result = pow( h, 10 )*f;
which is h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*f(x). Except (with the efficient version) I only call h once and just raise the result to the power 10.
I am trying to write code to do something similar (code written for demonstration purposes) to this:
template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
return foo([func](Args... args) -> std::result_of<F>::type
{
// Do something before calling func
func(args...);
// Do something after call func
});
}
So basically I am trying to write a function that returns an object that takes lambda that matches the templated function type. Obviously this code won't work because I do not have Args... defined. How would I solve this in C++11?
template<class F_before, class F, class F_after>
struct decorate_func_t {
F_before f0;
F f1;
F_after f2;
template<class...Args>
typename std::result_of<F(Args...)>::type operator()(Args&&...args)const{
f0();
auto r = f1(std::forward<Args>(args)...);
f2();
return r;
}
};
template<class F_before, class F, class F_after>
decorate_func_t<F_before, F, F_after>
decorate_func( F_before before, F f, F_after after ){
return {std::move(before), std::move(f), std::move(after)};
}
Then:
template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
return foo(decorate_func(
[]{/* Do something before calling func */},
func,
[]{/* Do something after call func */ }
};
}
the lack of auto parameters in C++11 lambdas makes this about the best you can do.
In C++14 this is trivial:
template <class F>
auto runFunc(F func)
{
return foo(
[func](auto&&... args) // ->decltype(auto) maybe
{
// Do something before calling func
auto r = func(decltype(args)(args)...);
// Do something after call func
return r;
}
);
}
note that many nominally C++11 compilers actually support auto parameters on lambdas.
You can use a support structure as in the following example:
#include<type_traits>
#include<cassert>
struct foo {
template<typename F>
foo(F f) { assert(42 == f(42)); }
};
template<typename>
struct S;
template<typename R, typename... Args>
struct S<R(*)(Args...)> {
template <typename F>
static auto runFunc(F func) -> foo
{
return foo{[func](Args... args) -> R
{
// Do something before calling func
auto r = func(args...);
// Do something after call func
return r;
}};
}
};
template<typename F>
inline auto runFunc(F func) -> foo
{
return S<F>::runFunc(func);
}
int f(int i) { return i; }
int main() {
runFunc(f);
}
For it's not clear to me what's the context of the problem, I'm not sure I got exactly what you were asking for.
I hope the code above can help you.
Still being unsure it this is what you're searching for, I risk posting:
#include <iostream>
struct foo
{
template<typename T>
foo(T lambda)
{
lambda(1, 2);
}
};
template <typename F, typename... Args>
inline typename std::result_of<F>::type runFunc(F func)
{
return foo(
[func](Args... args)
{
std::cout << "Before";
func(args...);
std::cout << "After";
}
);
}
struct print
{
void operator()(int i) const
{
std::cout << i << std::endl;
}
void operator()(int i, int j) const
{
std::cout << i << " " << j << std::endl;
}
};
int main()
{
runFunc<print, int, int>(print());
}
I'm trying to implement a generic curry function in C++14 that takes a callable object as an input parameter and allows currying.
Desired syntax:
auto sum3 = [](int x, int y, int z){ return x + y + z; };
int main()
{
assert(curry(sum3)(1)(1)(1) == 3);
auto plus2 = curry(sum3)(1)(1);
assert(plus2(1) == 3);
assert(plus2(3) == 5);
}
My implementation idea is as follows: have the curry function return an unary function that binds its argument to a future call to the original function, recursively. Call the bound original function on the "last recursive step".
Detecting the "last recursive step" is the problematic part.
My idea was detecting whether or not the current bound function (during the recursion) was legally callable with zero arguments, using a is_zero_callable type trait:
template <typename...>
using void_t = void;
template <typename, typename = void>
class is_zero_callable : public std::false_type
{
};
template <typename T>
class is_zero_callable<T, void_t<decltype(std::declval<T>()())>>
: public std::true_type
{
};
Unfortunately, I cannot seem to find a way to check the correct function for zero-argument "callability" - I need to somehow check if the function that will be returned from the currently bound function is zero-callable.
Here's what I've got so far (godbolt link):
template <typename TF, bool TLastStep>
struct curry_impl;
// Base case (last step).
// `f` is a function callable with no arguments.
// Call it and return.
template <typename TF>
struct curry_impl<TF, true>
{
static auto exec(TF f)
{
return f();
}
};
// Recursive case.
template <typename TF, bool TLastStep>
struct curry_impl
{
static auto exec(TF f)
{
// Bind `x` to subsequent calls.
return [=](auto x)
{
// This is `f`, with `x` bound as the first argument.
// (`f` is the original function only on the first recursive
// step.)
auto bound_f = [=](auto... xs)
{
return f(x, xs...);
};
// Problem: how to detect if we need to stop the recursion?
using last_step = std::integral_constant<bool, /* ??? */>;
// `is_zero_callable<decltype(bound_f)>{}` will not work,
// because `bound_f` is variadic and always zero-callable.
// Curry recursively.
return curry_impl<decltype(bound_f),
last_step{}>::exec(bound_f);
};
}
};
// Interface function.
template <typename TF>
auto curry(TF f)
{
return curry_impl<TF, is_zero_callable<decltype(f)>{}>::exec(f);
}
Is my approach/intuition viable? (Is it actually possible to stop the recursion by detecting whether or not we've reached a zero-arg-callable version of the original function?)
...or is there a better way of solving this problem?
(Please ignore the missing perfect forwarding and the lack of polish in the example code.)
(Note that I've tested this currying implementation using an user-specified template int TArity parameter to stop the recursion, and it worked properly. Having the user manually specify the arity of the original f function is unacceptable, however.)
The minimal changes required to make this work in Clang is
auto bound_f = [=](auto... xs) -> decltype(f(x, xs...))
// ^^^^^^^^^^^^^^^^^^^^^^^^^
{
return f(x, xs...);
};
using last_step = std::integral_constant<bool,
is_zero_callable<decltype(bound_f)>{}>;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Explicitly specifying the return type should make it SFINAE-friendly and capable of being detected by is_zero_callable. Unfortunately, GCC is unhappy with this, probably due to a bug.
A generic lambda is basically a class with a templated operator(), so we can just write it ourselves:
template<class F, class T>
struct bound_function {
F f;
T arg;
template<class... Args>
auto operator()(Args... args) const -> decltype(f(arg, args...)){
return f(arg, args...);
}
};
Note that I'm imitating the semantics of the generic lambda here and making the operator() const. A full-featured implementation will likely want to overload on constness and value categories.
Then
auto bound_f = bound_function<TF, decltype(x)>{f, x};
works in both GCC and Clang, but has a theoretical problem: when only f(arg) is valid (and not with extra arguments), then instantiating bound_function (which instantiates a declaration of its operator()) is ill-formed NDR because every valid specialization of operator()'s declaration requires an empty parameter pack.
To avoid this, let's specialize bound_function for the "no further arguments needed" case. And since we are computing this information anyway, let's just express it in a member typedef.
template<class F, class T, class = void>
struct bound_function {
using zero_callable = std::false_type;
F f;
T arg;
template<class... Args>
auto operator()(Args... args) const -> decltype(f(arg, args...)){
return f(arg, args...);
}
};
template<class F, class T>
struct bound_function<F, T, void_t<decltype(std::declval<const F&>()(std::declval<const T&>()))>> {
using zero_callable = std::true_type;
F f;
T arg;
decltype(auto) operator()() const {
return f(arg);
}
};
Then
auto bound_f = bound_function<TF, decltype(x)>{f, x};
using last_step = typename decltype(bound_f)::zero_callable;
under file check. please.
https://github.com/sim9108/Study2/blob/master/SDKs/curryFunction.cpp
// ConsoleApplication4.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <functional>
#include <type_traits>
// core function
template<typename FN, std::size_t N>
struct curry
{
FN fn_;
curry(FN fn) :fn_{ fn }
{
}
template<typename... TS, typename = std::enable_if_t< (N - sizeof...(TS)) != 0, int >>
auto operator()(TS... ts1) {
auto fn = [f = this->fn_, ts1...](auto... args) mutable {
return f(ts1..., args...);
};
return curry<decltype(fn), N - sizeof...(TS)>(fn);
}
template<typename... TS, typename Z = void, typename = std::enable_if_t< (N - sizeof...(TS)) == 0, int > >
auto operator()(TS... ts1) {
return fn_(ts1...);
}
};
//general make curry function
template<typename R, typename... Args>
auto make_curry(R(&f)(Args...)) {
auto fn = [&f](Args... args) {
return f(args...);
};
return curry<decltype(fn), sizeof...(Args)>(fn);
}
//general make curry member function
template<typename C, typename R, typename... Args>
auto make_curry(R(C::*f)(Args...), C c) {
auto fn = [f, c](Args... args) mutable {
return (c.*f)(args...);
};
return curry<decltype(fn), sizeof...(Args)>(fn);
}
template<typename C, typename R, typename... Args>
auto make_curry(R(C::*f)(Args...) const, C c) {
auto fn = [f, c](Args... args) mutable {
return (c.*f)(args...);
};
return curry<decltype(fn), sizeof...(Args)>(fn);
}
//general make curry lambda function
template<typename C>
auto make_curry(C&& c) {
using CR = std::remove_reference_t<C>;
return make_curry(&CR::operator(), c);
}
using std::string;
using std::function;
string func(string a, string b, string c) {
return "general function:" + a + b + c;
}
struct A {
string func(string a, string b, string c) {
return "member function:" + a + b + c;
};
};
int main(int argc, char* argv[])
{
{ //general function curry
auto c = make_curry(func);
auto m1 = c("t1")("t2")("t3");
auto m2 = c("test1")("test2")("test3");
auto m3 = c("m1");
auto m4 = m3("m2");
auto m5 = m4("m3");
std::cout << m5 << std::endl;
std::cout << m2 << std::endl;
std::cout << m5 << std::endl;
}
{ //member function curry
A a;
auto c = make_curry(&A::func, a);
auto m1 = c("t1")("t2")("t3");
auto m2 = c("test1")("test2")("test3");
auto m3 = c("m1");
auto m4 = m3("m2");
auto m5 = m4("m3");
std::cout << m1 << std::endl;
std::cout << m2 << std::endl;
std::cout << m5 << std::endl;
}
{ //lambda function curry
auto fn = [](string a, string b, string c) {
return "lambda function:" + a + b + c;
};
auto c = make_curry(fn);
auto m1 = c("t1")("t2")("t3");
auto m2 = c("test1")("test2")("test3");
auto m3 = c("m1");
auto m4 = m3("m2");
auto m5 = m4("m3");
std::cout << m1 << std::endl;
std::cout << m2 << std::endl;
std::cout << m5 << std::endl;
}
auto func3 = make_curry(func);
std::cout << func3("Hello, ")( "World!", " !hi") << std::endl;
std::cout << func3("Hello, ","World!")(" !hi") << std::endl;
std::cout << func3("Hello, ","World!", " !hi") << std::endl;
std::cout << func3()("Hello, ", "World!", " !hi") << std::endl;
return 0;
}
I am currently coding some cryptographic algorithms in C++11 that require a lot of function compositions. There are 2 types of composition I have to deal with :
Compose a function on itself a variable number of times. Mathematically, for a certain function F, F^n(x) = (F^{n-1} o F)(x) = F^{n-1}(F(x)).
Compose different functions together. For example, for some functions f,g,h,i,j and k of the same type, I'll have f(g(h(i(j(k(x)))))).
In my case, I'm using the following definition of F :
const std::vector<uint8_t> F(const std::vector<uint8_t> &x);
I would like to compose this function on itself n times. I have implemented the composition in a simple recursive way which is working fine :
const std::vector<uint8_t> compose(const uint8_t n, const std::vector<uint8_t> &x)
{
if(n > 1)
return compose(n-1, F(x));
return F(x);
}
For this case, is there a more efficient way an proper way to implement this composition using c++11 but without using BOOST ?
It would be great to use this form if it is possible of course :
answer = compose<4>(F)(x); // Same as 'answer = F^4(x) = F(F(F(F(x))))'
For the second case, I would like to implement the composition of a variable number of functions. For a given set of functions F0, F1, ..., Fn having the same definition as F, is there an efficient and proper way to compose them where n is variable ?
I think variadic template would be useful here, but I don't know how to use them in that case.
Thanks for your help.
Something along these lines, perhaps (untested):
template <typename F>
class Composer {
int n_;
F f_;
public:
Composer(int n, F f) : n_(n), f_(f) {}
template <typename T>
T operator()(T x) const {
int n = n_;
while (n--) {
x = f_(x);
}
return x;
}
};
template <int N, typename F>
Composer<F> compose(F f) {
return Composer<F>(N, f);
}
EDIT: And for the second case (tested this time):
#include <iostream>
template <typename F0, typename... F>
class Composer2 {
F0 f0_;
Composer2<F...> tail_;
public:
Composer2(F0 f0, F... f) : f0_(f0), tail_(f...) {}
template <typename T>
T operator() (const T& x) const {
return f0_(tail_(x));
}
};
template <typename F>
class Composer2<F> {
F f_;
public:
Composer2(F f) : f_(f) {}
template <typename T>
T operator() (const T& x) const {
return f_(x);
}
};
template <typename... F>
Composer2<F...> compose2(F... f) {
return Composer2<F...>(f...);
}
int f(int x) { return x + 1; }
int g(int x) { return x * 2; }
int h(int x) { return x - 1; }
int main() {
std::cout << compose2(f, g, h)(42);
return 0;
}
Thanks for the fun question, Gabriel of year 2013.
Here is a solution. It works in c++14.
#include <functional>
#include <iostream>
using std::function;
// binary function composition for arbitrary types
template <class F, class G> auto compose(F f, G g) {
return [f, g](auto x) { return f(g(x)); };
}
// for convienience
template <class F, class G> auto operator*(F f, G g) { return compose(f, g); }
// composition for n arguments
template <class F, typename... Fs> auto compose(F f, Fs &&... fs) {
return f * compose(fs...);
}
// composition for n copies of f
template <int i, class F>
// must wrap chain in a struct to allow partial template specialization
struct multi {
static F chain(F f) { return f * multi<i - 1, F>::chain(f); }
};
template <class F> struct multi<2, F> {
static F chain(F f) { return f * f; }
};
template <int i, class F> F compose(F f) { return multi<i, F>::chain(f); }
int main(int argc, char const *argv[]) {
function<double(int)> f = [](auto i) { return i + 3; };
function<int(double)> g = [](auto i) { return i * 2; };
function<int(int)> h = [](auto i) { return i + 1; };
std::cout << '\n'
<< "9 == " << compose(f, g, f)(0) << '\n'
<< "5 == " << (f * g * h)(0) << '\n'
<< "100 == " << compose<100>(h)(0) << '\n';
return 0;
}
You can define
Matrix compose(Matrix f, Matrix g);
or
Rotation compose(Rotation f, Rotation g);
to reuse this code for all sorts of things.
A very general example (g++ -std=c++1y composition.cpp):
// ---------------------------------------------------------
// "test" part
// ---------------------------------------------------------
int f(int a) { return 2*a; }
double g(int a) { return a+2.5; }
double h(double a) { return 2.5*a; }
double i(double a) { return 2.5-a; }
class Functor {
double x;
public:
Functor (double x_) : x(x_) { }
double operator() (double a) { return a*x; }
};
// ---------------------------------------------------------
// ---------------------------------------------------------
int main () {
auto l1 = [] (double a) { return a/3; };
auto l2 = [] (double a) { return 3.5+a; };
Functor fu {4.5};
auto compos1 = compose (f, g, l1, g, h, h, l1, l2);
auto compos2 = compose (compos1, l1, l2, fu);
auto x = compos2 (3);
cout << x << endl;
cout << compos2(3) << endl;
cout << fu(l2(l1(l2(l1(h(h(g(l1(g(f(3))))))))))) << endl;
} // ()
Library part:
// ---------------------------------------------------------
// "library" part
// ---------------------------------------------------------
template<typename F1, typename F2>
class Composite{
private:
F1 f1;
F2 f2;
public:
Composite(F1 f1, F2 f2) : f1(f1), f2(f2) { }
template<typename IN>
decltype(auto) operator() (IN i)
{
return f2 ( f1(i) );
}
};
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename F2>
decltype(auto) compose (F1 f, F2 g) {
return Composite<F1, F2> {f,g};
}
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename... Fs>
decltype(auto) compose (F1 f, Fs ... args)
{
return compose (f, compose(args...));
}
The whole program:
// g++ -std=c++1y composition.cpp
#include <iostream>
using namespace std;
// ---------------------------------------------------------
// "library" part
// ---------------------------------------------------------
template<typename F1, typename F2>
class Composite{
private:
F1 f1;
F2 f2;
public:
Composite(F1 f1, F2 f2) : f1(f1), f2(f2) { }
template<typename IN>
decltype(auto) operator() (IN i)
{
return f2 ( f1(i) );
}
};
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename F2>
decltype(auto) compose (F1 f, F2 g) {
return Composite<F1, F2> {f,g};
}
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename... Fs>
decltype(auto) compose (F1 f, Fs ... args)
{
return compose (f, compose(args...));
}
// ---------------------------------------------------------
// "test" part
// ---------------------------------------------------------
int f(int a) { return 2*a; }
double g(int a) { return a+2.5; }
double h(double a) { return 2.5*a; }
double i(double a) { return 2.5-a; }
class Functor {
double x;
public:
Functor (double x_) : x(x_) { }
double operator() (double a) { return a*x; }
};
// ---------------------------------------------------------
// ---------------------------------------------------------
int main () {
auto l1 = [] (double a) { return a/3; };
auto l2 = [] (double a) { return 3.5+a; };
Functor fu {4.5};
auto compos1 = compose (f, g, l1, g, h, h, l1, l2);
auto compos2 = compose (compos1, l1, l2, fu);
auto x = compos2 (3);
cout << x << endl;
cout << compos2(3) << endl;
cout << fu(l2(l1(l2(l1(h(h(g(l1(g(f(3))))))))))) << endl;
} // ()
Here is a simple c++14 solution (it may probably be re-written to c++11):
#include <iostream>
// base condition
template <typename F>
auto compose(F&& f)
{
return [a = std::move(f)](auto&&... args){
return a(std::move(args)...);
};
}
// recursive composition
// from compose(a, b, c...) to compose(ab, c...)
template <typename F1, typename F2, typename... Fs>
auto compose(F1&& f1, F2&& f2, Fs&&... fs)
{
return compose(
[first = std::move(f1), second = std::move(f2)]
(auto&&... args){
return second(first(std::move(args)...));
},
std::move(fs)...
);
}
Possible usage:
int main()
{
const auto f = compose(
[](const auto n){return n * n;},
[](const auto n){return n + 2;},
[](const auto n){return n + 2;}
);
std::cout << f(10) << std::endl; // outputs 104
}
Here is a link to the repo with a few more examples: https://github.com/nestoroprysk/FunctionComposition
A quick implementation of function iteration with argument forwarding. The helper type is unfortunately necessary because function templates can’t be partially specialised.
#include <functional>
#include <iostream>
using namespace std;
template<int n, typename A>
struct iterate_helper {
function<A(A)> f;
iterate_helper(function<A(A)> f) : f(f) {}
A operator()(A&& x) {
return f(iterate_helper<n - 1, A>(f)(forward<A>(x)));
};
};
template<typename A>
struct iterate_helper<1, A> {
function<A(A)> f;
iterate_helper(function<A(A)> f) : f(f) {}
A operator()(A&& x) {
return f(forward<A>(x));
};
};
template<int n, typename A>
function<A(A)> iterate(function<A(A)> f) {
return iterate_helper<n, A>(f);
}
int succ(int x) {
return x + 1;
}
int main() {
auto add5 = iterate<5>(function<int(int)>(succ));
cout << add5(10) << '\n';
}
You haven't shown the body of F, but if you can modify it so that it mutates the input to form the output then change the signature to:
void F(std::vector<uint8_t>& x);
Thereafter you can implement Fn as:
void Fn(std::vector<uint8_t>& x, size_t n)
{
for (size_t i = 0; i < n; i++)
F(x);
}
The compiler will unroll the loop for you if it is more efficient, but even if it doesn't an increment/compare of a local variable will be orders of magnitude faster than calling F.
You can then explcitly copy-construct new vectors when you actually want to make a copy:
vector<uint8_t> v1 = ...;
vector<uint8_t> v2 = v1; // explicitly take copy
Fn(v2,10);
What about (untested):
template < typename Func, typename T >
T compose_impl( Func &&, T &&x, std::integral_constant<std::size_t, 0> )
{ return std::forward<T>(x); }
template < typename Func, typename T, std::size_t N >
T compose_impl( Func &&f, T &&x, std::integral_constant<std::size_t, N> )
{
return compose_impl( std::forward<Func>(f),
std::forward<Func>(f)(std::forward<T>( x )),
std::integral_constant<std::size_t, N-1>{} );
}
template < std::size_t Repeat = 1, typename Func, typename T >
T compose( Func &&f, T &&x )
{
return compose_impl( std::forward<Func>(f), std::forward<T>(x),
std::integral_constant<std::size_t, Repeat>{} );
}
We can use variadic function templates for multiple functions (untested):
template < typename Func, typename T >
constexpr // C++14 only, due to std::forward not being constexpr in C++11
auto chain_compose( Func &&f, T &&x )
noexcept( noexcept(std::forward<Func>( f )( std::forward<T>(x) )) )
-> decltype( std::forward<Func>(f)(std::forward<T>( x )) )
{ return std::forward<Func>(f)(std::forward<T>( x )); }
template < typename Func1, typename Func2, typename Func3, typename ...RestAndT >
constexpr // C++14 only, due to std::forward
auto chain_compose( Func1 &&f, Func2 &&g, Func3 &&h, RestAndT &&...i_and_x )
noexcept( CanAutoWorkHereOtherwiseDoItYourself )
-> decltype( auto ) // C++14 only
{
return chain_compose( std::forward<Func1>(f),
chain_compose(std::forward<Func2>( g ), std::forward<Func3>( h ),
std::forward<RestAndT>( i_and_x )...) );
}
The upcoming decltype(auto) construct automatically computes the return type from an inlined function. I don't know if there's a similar automatic computation for noexcept