顺序异构函数执行器

svo*_*ron 4 c++ inheritance types template-meta-programming c++11

让我们假设有N个函数采用不同的输入并返回不同的值:

int h(int);
string g(int);
double f(string);
Run Code Online (Sandbox Code Playgroud)

当然可以这样写:

f(g(h(4)))  
Run Code Online (Sandbox Code Playgroud)

现在假设我想将这些函数f,g,h存储到一种容器中,如:

Container c;
c.add(h);
c.add(g);
c.add(f); 
Run Code Online (Sandbox Code Playgroud)

给定第一个函数的输入(在f的情况下为int)我希望这些函数以顺序方式执行,每个函数都将前一个函数的输出作为输入.

你认为在C++中有可能吗?可能没有使用dynamic_cast和使用C++ 11

Vit*_*meo 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)));
    }
};
Run Code Online (Sandbox Code Playgroud)

用法:

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';
}
Run Code Online (Sandbox Code Playgroud)

输出:

1

wandbox.org上的实例


可能的递归实现:

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);
}
Run Code Online (Sandbox Code Playgroud)

  • @svoltron:你需要某种类型的擦除.它很容易达到`std :: function`而不是尝试自己滚动. (2认同)