让我们假设有N个函数接受不同的输入并返回不同的值:
int h(int);
string g(int);
double f(string);
当然可以写类似的东西:
f(g(h(4)))
现在假设我要将这些函数f,g,h存储到一种容器中,例如:
Container c;
c.add(h);
c.add(g);
c.add(f);
给出第一个函数的输入(在f情况下为int),我希望这些函数以顺序的方式执行,每个函数都将前一个函数的输出作为输入。
您认为C ++有可能吗?可能不使用dynamic_cast也不使用C ++ 11
答案 0 :(得分:6)
如果Container
需要在运行时进行修改,则可以使用std::any
(或boost::any
)来实现:
struct Container
{
std::vector<std::function<std::any(std::any)>> _fns;
template <typename R, typename A>
void add(R(*f)(A))
{
_fns.emplace_back([f](std::any x) -> std::any
{
return {f(std::any_cast<A>(x))};
});
}
template <typename T>
std::any call(T x)
{
// TODO: replace with recursive version
return _fns[2](_fns[1](_fns[0](x)));
}
};
用法:
int h(int x) { return x; }
std::string g(int x) { return std::to_string(x); }
double f(std::string x) { return x.size(); }
int main()
{
Container c;
c.add(h);
c.add(g);
c.add(f);
std::cout << std::any_cast<double>(c.call(5)) << '\n';
}
输出:
1
可能的递归实现:
template <typename T>
std::any call_impl(T x, const std::size_t next)
{
return next == _fns.size() - 1
? _fns[next](x)
: call_impl(_fns[next](x), next + 1);
}
template <typename T>
std::any call(T x)
{
return call_impl(x, 0);
}
答案 1 :(得分:1)
这更多是一个旁注,但我在假期期间做了一些非常有趣的事情。这里没有太多代码,但是您可以检查代码here或实时版本here。
基本上,这是一个函数,它返回捕获所有要调用的函数的lambda。这使您可以编写以下代码:
#include <iostream>
#include <string>
#include "chain.hpp"
int f(int x) { return x; }
std::string g(int x) { return std::to_string(x); }
double h(std::string x) { return x.size(); }
int main() {
auto function = fn::chain(f, g, h);
std::cout << function(5) << '\n'; // prints 1
return 0;
}
如果std :: invoke不起作用,它还将尝试使用std :: apply扩展已删除的元组。这使以下代码有效:
#include <iostream>
#include <tuple>
#include "chain.hpp"
int main() {
auto test = fn::chain([](int i, int j) { return i + j; },
[](int i) { return i * 2; },
[](int i) -> std::tuple<int, int> {
return {i, i};
},
[](int i, int j) { return i + j; });
std::cout << test(1, 2) << '\n'; // prints 12
}
正如我所说,这只是一个有趣的实验,但也许会有所帮助!