C++ 如何在C++;?

C++ 如何在C++;?,c++,templates,chain-of-responsibility,C++,Templates,Chain Of Responsibility,下面的代码允许我实例化并调用void()函数列表 (如果您希望编译和运行此代码,我将使用它进行单元测试) #包括“catch.hpp” #包括 #包括 类:public std::vector,public std::function { 公众: void运算符()()常量 { 对于(std::vector::const_迭代器it=begin();it!=end();++it){ (*it)(); } } }; 测试用例(“责任链在被调用时调用其成员”) { 布尔测试函数调用=false; s

下面的代码允许我实例化并调用
void()
函数列表

(如果您希望编译和运行此代码,我将使用它进行单元测试)

#包括“catch.hpp”
#包括
#包括
类:public std::vector,public std::function
{
公众:
void运算符()()常量
{
对于(std::vector::const_迭代器it=begin();it!=end();++it){
(*it)();
}
}
};
测试用例(“责任链在被调用时调用其成员”)
{
布尔测试函数调用=false;
std::函数测试_函数=[&]()
{
test_function_called=true;
};
受测试的责任对象链;
对象在测试中。向后推(测试功能);
对象_在_测试()下;
要求(调用测试函数);
}
我的问题是如何对
责任链
类进行模板化,以接受具有不同(但一致)签名的函数

例如,考虑<代码>责任> <代码>或<代码>责任> /代码> ./p> 为了便于讨论,假设第二个示例返回链中最后一个成员返回的值,或者如果链为空,则返回ReturnClass的默认值

另外,如果STL已经包含了一个实现这一点的模板类,那么我更愿意将其用于我自己开发的类。

您的特定“放弃所有中间结果”也相当简单,但我认为这是一个坏主意

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;
    }
};
请注意,从
std::
类型派生是一个坏主意,尤其是
std::function
,它是一种类型擦除可调用,而不是“所有可调用的基础”。您只需提供一个
操作符()

改进非无效案例的选项:

    // 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;
    }
//折叠结果
模板
Ret运算符()(Args…Args,二进制函数add,Ret init)常量
{
用于(自动和功能:链){
init=add(init,func(args…);
}
返回init;
}
//返回向量
模板
std::vector操作符()(Args…Args)常量
{
std::向量结果(chain.size());
用于(自动和功能:链){
结果。推回(func(args…);
}
返回结果;
}
您不需要使用作为基类,使用就足够了。模板
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;
}
您还可以编写函数模板,而不是重载
运算符()

模板
R执行(常量标准::向量和函数,
常量参数(&…参数){
R结果{};
用于(自动和测试功能)
结果=试验结果(4,2);
返回结果;
}

由于您使用的是
std::function
,因此您的代码需要C++11,因此您也可以对
使用
auto
和基于范围的
。这将允许更干净的代码。为什么您需要从
std::vector
std::function
?@el.pescado感谢您的提示!我还没有在C++中编程过一段时间。所以我不知道更新的特性。@Gruffalo我从std::vector派生出来,免费获得所有的向量操作(如push_back、insert和swap)。我从std::function派生,因此实例是可嵌套的。如果有更好的方法,我洗耳恭听…@Gruffalo发现,我不需要从std::function派生来使实例可嵌套。谢谢你让我大开眼界!
    // 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;
    }
#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;
}
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;
}
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;
}