std::函数的复合模式
Composite pattern of std::functions
我正在尝试使用模板类实现std::functions
复合模式,其中每个复合类处理其子类的返回值。
因此,模式类可能如下所示:
class AbstractClass {
public:
virtual void process() = 0;
};
template<typename ReturnType>
class PrimitiveClass : public AbstractClass {
public:
ReturnType process() {
// please note, that the result is not returned by the return statement
return this->func(); //this is just for simplicity
}
private:
std::function<ReturnType()> func;
}
template<typename ReturnType, typename ...Args>
class CompositeClass : public AbstractClass {
public:
ReturnType process() {
// --> This is where I want to process all children first and then pass their return values to this->func
// the following code is kind of a pseudo code:
for(auto it = vector.begin(); it != vector.end(); ++it {
results.add((**it).process())
}
return this->func(results)
}
private:
std::function<ReturnType(Args...)> func;
std::vector<std::shared_ptr<AbstractClass>> children;
};
例如,我有一个带有std::function<int(int, double, bool)
的CompositeClass
,该函数的参数类型也是其子函数的ReturnType
。我想将孩子的返回值传递给上述std::function
谁能想到一种方法,我该如何实现这一目标?
如果我明白你想要什么(如果我没有错的话)......
(1)为了解决process()
的无协变返回值的问题(参见Igor Tandetnik的评论),你需要一个模板抽象类来表达正确的返回值;
template <typename T>
struct abstClass
{ virtual T process() const = 0; };
(2)所以你的CompositeClass
(在我的例子中更名为nodeClass
)继承自abstClass<ReturnType>
(3)你的PrimitiveClass
是无用的,因为你可以将案例(引用没有参数的函数)作为零CompositeClass
进行管理Args
(4) 您需要一个leafClass
来处理基本值
(5)在CompositeClass
(nodeClass
),children
,而不是shared_ptr<AbstractClass>
的std::vector
(不能做你想做的事),可以是一个
std::tuple<std::shared_ptr<abstClass<Args>>...> children;
鉴于这些要点,我提出了以下解决方案(不幸的是,它是 C++14,因为使用从 C++14 开始可用的std::index_sequence
和std::make_index_sequence
;但如果你需要一个 C++11 解决方案,写替代品并不难)
#include <tuple>
#include <memory>
#include <iostream>
#include <functional>
template <typename T>
struct abstClass
{ virtual T process() const = 0; };
template <typename T>
class leafClass : public abstClass<T>
{
private:
T value;
public:
leafClass (T && v0) : value { std::forward<T>(v0) }
{ }
T process () const
{ return value; };
};
template <typename RetT, typename ... ArgTs>
class nodeClass : public abstClass<RetT>
{
private:
using funcT = std::function<RetT(ArgTs...)>;
template <typename T>
using shrPAC = std::shared_ptr<abstClass<T>>;
funcT func;
std::tuple<shrPAC<ArgTs>...> childrens;
template <std::size_t ... Is>
RetT processH (std::index_sequence<Is...> const &) const
{ return func(std::get<Is>(childrens)->process()...); }
public:
nodeClass (funcT && f0, shrPAC<ArgTs> && ... as)
: func { std::forward<funcT>(f0) },
childrens { std::forward<shrPAC<ArgTs>>(as)... }
{ }
RetT process () const
{ return processH(std::make_index_sequence<sizeof...(ArgTs)>{}); }
};
int main ()
{
auto func0 = [](int i, double d, bool b) { return int( b ? i+d : i-d ); };
auto shpLci = std::make_shared<leafClass<int>>(1);
auto shpLcd = std::make_shared<leafClass<double>>(2.2);
auto shpNb = std::make_shared<nodeClass<bool>>([](){ return true; });
auto shpNc0 = std::make_shared<nodeClass<int, int, double, bool>>
(func0, shpLci, shpLcd, shpNb);
auto shpNc1 = std::make_shared<nodeClass<int, int, double, bool>>
(func0, shpNc0, shpLcd, shpNb);
auto shpNc2 = std::make_shared<nodeClass<int, int, double, bool>>
(func0, shpNc1, shpLcd, shpNb);
std::cout << shpNc0->process() << std::endl; // print 3
std::cout << shpNc1->process() << std::endl; // print 5
std::cout << shpNc2->process() << std::endl; // print 7
}
相关文章:
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 为什么在保护模式下继承升级不起作用
- 如何在全屏模式下(在OpenGL中)使背景透明
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 返回复合模式的复合对象不返回整个对象
- std::函数的复合模式
- 可以混合复合模式和奇怪的重复模板模式
- 寻找Boost转换迭代器的复合特征模式
- 在复合模式中搜索特定元素
- 未能在复合/迭代器设计模式中看到真正的价值
- 如果复合模式中的每个复合项都有其自己的许多独特属性,是否可以
- 在树视图中使用复合模式是否有意义
- 不同类型的复合模式重用
- GOF复合设计模式CompositeObject::删除C++中的递归实现
- 通过复合状态列表模式进行迭代
- 复合模式中的内存管理
- 复合模式:复制树结构
- C++:应用复合模式
- 如何使用复合模式实现菜单