键入擦除。该库提供渲染(某些_数据)函数。
我们从几种节点开始。基本体是渲染(基本体)仅绘制某些内容的节点。
列表节点有子节点,渲染(List_节点)绘制其内容。
generic_节点存储具有渲染(?)的任何内容超载。它会删除渲染(?)活动调用render(generic_节点)对包含的数据调用该类型的擦除操作。
list_节点包含泛型_节点的向量。
为了添加新的渲染类型,您只需定义一个新类型,重载渲染(new\u type),然后将其存储在泛型节点中。
struct render_target {
// stuff about the thing we are rendering on
};
struct renderable_concept {
virtual ~renderable_concept() {}
virtual void render_on( render_target* ) const = 0;
};
template<class T>
void render( render_target*, T const& ) = delete; // by default, nothing renders
struct emplace_tag {};
template<class T>
struct renderable_model : renderable_concept {
T t;
template<class...Us>
renderable_model( emplace_tag, Us&&...us ):
t{std::forward<Us>(us)...}
{}
void render_on( render_target* target ) const final override {
render( target, t );
}
};
template<class T>
struct emplace_as {};
struct generic_node {
friend void render( render_target* target, generic_node const& node ) {
if (!node.pImpl) return;
node.pImpl->render_on(target);
}
template<class T, class...Us>
generic_node( emplace_as<T>, Us&&... us):
pImpl( std::make_shared<renderable_model<T>>(emplace_tag{}, std::forward<Us>(us)...) )
{}
generic_node() = default;
generic_node(generic_node&&)=default;
generic_node(generic_node const&)=default;
generic_node& operator=(generic_node&&)=default;
generic_node& operator=(generic_node const&)=default;
private:
std::shared_ptr<renderable_concept> pImpl;
};
现在,如何创建列表节点。
struct list_node {
std::vector<generic_node> nodes;
friend void render( render_target* target, list_node const& self ) {
for (auto&& node:self.nodes)
render(target, node);
}
list_node(std::vector<generic_node> ns):nodes(std::move(ns)) {}
list_node() = default;
list_node(list_node&&)=default;
list_node& operator=(list_node&&)=default;
};
template<class T, class...Args>
generic_node make_node( Args&&... args ) {
return {emplace_as<T>{}, std::forward<Args>(args)...};
}
template<class T>
generic_node make_node( T&& t ) {
return {emplace_as<std::decay_t<T>>{}, std::forward<T>(t) };
}
struct printing_node {
std::string message;
friend void render( render_target* target, printing_node const& self ) {
std::cout << self.message;
}
};
测试代码:
auto list = make_node( list_node{{
make_node( printing_node{{"hello"}} ),
make_node( printing_node{{"world"}} )
}});
render_target target;
render(&target, list);
Live example
.