如何概括调用C++中的函数列表?

spi*_*epf 4 c++ templates chain-of-responsibility

我有以下代码,允许我实例化然后调用void()函数列表.

(如果您希望编译并运行此代码,我使用https://github.com/philsquared/Catch进行单元测试).

#include "catch.hpp"

#include <functional>
#include <vector>

class ChainOfResponsibility : public std::vector<std::function<void()> >, public std::function<void()>
{
public:
    void operator()() const
    {
        for(std::vector<std::function<void()> >::const_iterator it = begin(); it != end(); ++it) {
            (*it)();
        }
    }
};

TEST_CASE("ChainOfResponsibility calls its members when invoked")
{
    bool test_function_called = false;
    std::function<void()> test_function = [&]()
    {
        test_function_called = true;
    };

    ChainOfResponsibility object_under_test;

    object_under_test.push_back(test_function);
    object_under_test();

    REQUIRE(test_function_called);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是如何模拟ChainOfResponsibility类接受具有不同(但一致)签名的函数?

例如,考虑a ChainOfResponsibility<void(int)>或a ChainOfResponsibility<ReturnClass(Argument1Class, Argument2Class)>.

为了参数,我们假设第二个示例返回链中最后一个成员返回的值,如果链为空,则返回ReturnClass的默认值.

此外,如果STL已经包含了实现此目的的模板类,那么我宁愿在我的本土类中使用它.

Cal*_*eth 7

你的具体"丢弃所有中间结果"也相当简单,但我认为这是一个坏主意.

template<typename Ret, typename ... Args>
class ChainOfResponsibility
{
    std::vector<std::function<Ret(Args...)> > chain;
public:
    Ret operator()(Args ... args) const
    {
        Ret value;
        for(auto & func : chain) {
            value = func(args...);
        }
        return value;
    }
};
Run Code Online (Sandbox Code Playgroud)

void 必须自己对待它

template<typename ... Args>
class ChainOfResponsibility<void, Args...>
{
    std::vector<std::function<void(Args...)> > chain;
public:
    void operator()(Args ... args) const
    {
        for(auto & func : chain) {
            func(args...);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意,从std::类型派生是一个坏主意,特别是std::function,它是一种类型擦除可调用,而不是"所有可调用的基础".你可以简单地提供一个operator()

改善非空洞案件的选择:

    // fold the results
    template <typename BinaryFunction>
    Ret operator()(Args ... args, BinaryFunction add, Ret init) const
    {
        for(auto & func : chain) {
            init = add(init, func(args...));
        }
        return init;
    }

    // return a vector
    template <typename BinaryFunction>
    std::vector<Ret> operator()(Args ... args) const
    {
        std::vector<Ret> results(chain.size());
        for(auto & func : chain) {
            results.push_back(func(args...));
        }
        return results;
    }
Run Code Online (Sandbox Code Playgroud)