How to summarize a function list call in C ++?

I have the following code that allows me to instantiate and then call a list of functions void().

(I use https://github.com/philsquared/Catch for unit testing if you want to compile and run this code).

#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);
}

My question is how to create a class template ChainOfResponsibilityfor accepting functions with a different (but consistent) signature?

For example, consider a ChainOfResponsibility<void(int)>or ChainOfResponsibility<ReturnClass(Argument1Class, Argument2Class)>.

As an argument, let's say that the second example returns the value returned by the last member in the chain, or the default value for ReturnClass if the chain is empty.

, STL , , .

+4
2

" " , , .

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;
    }
};

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...);
        }
    }
};

, std:: - , std::function, , " ". operator()

-void case:

    // 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;
    }
+7

std::function , std::vector. ChainOfResponsibility , std::function:

#include <iostream>
#include <string>
#include <functional>
#include <vector>

template<typename>
class ChainOfResponsibility;

template<typename R, typename... Args>
class ChainOfResponsibility<R(Args...)> :
        public std::vector<std::function<R(Args...)>> {
public:
    R operator()(const Args&... args) {
        R result {};

        for(auto it = this->begin(); it != this->end(); ++it)
            result = (*it)(args...);

        return result;
    }
};

int main() {
    ChainOfResponsibility<std::string(int, int)> tester;

    tester.push_back([](int a, int b)->std::string {
        return std::to_string(a + b);
    });

    std::cout << tester(4, 2) << std::endl;
}

, std::vector . operator() , :

int main() {
    std::vector<std::function<std::string(int, int)>> tester;

    tester.push_back([](int a, int b)->std::string {
        return std::to_string(a + b);
    });

    std::string result;

    for(auto& test_fn : tester)
        result = test_fn(4, 2);

    std::cout << result << std::endl;
}

operator():

template<typename R, typename... Args>
R perform(const std::vector<std::function<R(Args...)>>& functions,
        const Args&... args) {
    R result {};
    for(auto& test_fn : functions)
        result = test_fn(4, 2);
    return result;
}
+1

Source: https://habr.com/ru/post/1683940/


All Articles