Functional composition with variable patterns

My goal is to get the exact composition of functions that work with this syntax :

int main() {
    Function<std::string, int> f([](const std::string& s) {return s.length();});
    Function<int, double> g([](int x) {return x + 0.5;});
    Function<double, int> h([](double d) {return int(d+1);});
    std::cout << compose(g, f, "hello") << '\n';  // g(f("hello")) = 5.5
    std::cout << compose(h, g, f, "hello") << '\n';  // h(g(f("hello"))) = 6
}

Having changed the syntax a bit so that the argument "hello"goes first, I easily work with the following code:

#include <iostream>
#include <functional>
#include <tuple>
#include <string>

template <typename D, typename R>
struct Function {
    using domain = const D&;
    using range = R;
    using function = std::function<range(domain)>;
    const function& f;
    Function (const function& f) : f(f) {}
    range operator()(domain x) const {return f(x);}
};

template <typename... Ts>
struct LastType {
    using Tuple = std::tuple<Ts...>;
    using type = typename std::tuple_element<std::tuple_size<Tuple>::value - 1, Tuple>::type;
};

template <typename F, typename G>
typename G::range compose (const typename F::domain& x, const G& g, const F& f) {
    return g(f(x));
}

template <typename F, typename... Rest>
auto compose (const typename LastType<Rest...>::type::domain& x, const F& f, const Rest&... rest) {
    return f(compose(x, rest...));
}

int main() {
    Function<std::string, int> f([](const std::string& s) {return s.length();});
    Function<int, double> g([](int x) {return x + 0.5;});
    Function<double, int> h([](double d) {return int(d+1);});
    std::cout << compose("hello", g, f) << '\n';  // g(f("hello")) = 5.5
    std::cout << compose("hello", h, g, f) << '\n';  // h(g(f("hello"))) = 6
}

Having done this, I thought it would be a trivial task to adapt the above code to get the exact syntax I want (i.e. with the "hello" at the end of the list), but it becomes more complicated than I thought. I tried to do the following:

#include <iostream>
#include <functional>
#include <tuple>
#include <string>

template <typename D, typename R>
struct Function {
    using domain = const D&;
    using range = R;
    using function = std::function<range(domain)>;
    const function& f;
    Function (const function& f) : f(f) {}
    range operator()(domain x) const {return f(x);}
};

template <typename F, typename G>
typename G::range compose (const G& g, const F& f, const typename F::domain& x) {
    return g(f(x));
}

template <typename F, typename... Rest>
auto compose (const F& f, const Rest&... rest) {
    return f(compose(rest...));
}

int main() {
    Function<std::string, int> f([](const std::string& s) {return s.length();});
    Function<int, double> g([](int x) {return x + 0.5;});
    Function<double, int> h([](double d) {return int(d+1);});
    std::cout << compose(g, f, "hello") << '\n';  // g(f("hello")) = 5.5
    std::cout << compose(h, g, f, "hello") << '\n';  // h(g(f("hello"))) = 6
}

And I don’t know how to fix it. Can someone help me fix this?

, , compose_, args... ( std::tuple ), , compose. , , , ( ) .

+4
2

?

#include <iostream>    
#include <functional>
#include <tuple>
#include <string>

template <typename D, typename R>
struct Function {
    using domain = const D&;
    using range = R;
    using function = std::function<range(domain)>;
    const function& f;
    Function (const function& f) : f(f) {}
    range operator()(domain x) const {return f(x);}
};

template <typename F, typename X = typename F::domain>
typename F::range compose (const F& f, const X & x) {
    return f(x);
}

template <typename F, typename... Rest>
typename F::range  compose (const F& f, const Rest&... rest) {
    return f(compose(rest...));
}

int main() {
    Function<std::string, int> f([](const std::string& s) {return    s.length();});
    Function<int, double> g([](int x) {return x + 0.5;});
    Function<double, int> h([](double d) {return int(d+1);});
    std::cout << compose(g, f, "hello") << '\n';  // g(f("hello")) = 5.5
    std::cout << compose(h, g, f, "hello") << '\n';  // h(g(f("hello"))) = 6
}

auto compose() ++ 14 ( ).

, compose() N N , final (not varidic) 2 3 . , . , ( ) : . typename X = typename F::domain ( const typename F::domain& const X&), , ( , c++ ++) [ ; ]

p.s.: .

+1

, :

template <typename T>
const T& compose (const T& t) {
    return t;
}

template <typename F, typename... Rest>
typename F::range compose(const F& f, Rest... rest) {
    return f(compose(rest...));
}
+2

All Articles