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';
std::cout << compose(h, g, f, "hello") << '\n';
}
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';
std::cout << compose("hello", h, g, f) << '\n';
}
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';
std::cout << compose(h, g, f, "hello") << '\n';
}
And I don’t know how to fix it. Can someone help me fix this?
, , compose_, args... ( std::tuple ), , compose. , , , ( ) .