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已经包含了实现此目的的模板类,那么我宁愿在我的本土类中使用它.
你的具体"丢弃所有中间结果"也相当简单,但我认为这是一个坏主意.
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)
| 归档时间: |
|
| 查看次数: |
138 次 |
| 最近记录: |