【发布时间】:2016-06-27 20:45:01
【问题描述】:
我的目标是让函数组合使用这种精确语法:
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
}
通过稍微改变语法,让 "hello" 参数先出现,我可以轻松地使用以下代码:
#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
}
完成之后,我认为修改上述代码以便获得我想要的确切语法(即“hello”位于列表末尾)将是一项微不足道的任务,但它变得更加困难比我想象的要好。我尝试了以下方法,但无法编译:
#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
}
而且我不知道如何解决它。谁能帮我解决这个问题?
我想出的一个新想法是定义compose_,它将重新排序args... 的参数(通过一些std::tuple 操作),以便第一个元素放在最后,然后将该参数包传递给compose。不过这看起来很混乱,即使它有效,也必须有一个更直接(更短)的解决方案。
【问题讨论】:
-
或许this ?
-
@Piotr Skotnicki 太棒了!我试图弄清楚为什么你的编译为什么我的不编译。
标签: c++ c++11 templates variadic-templates variadic