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