可变 class 模板的循环模板依赖
Circular template dependecy of variadic class templates
我正在尝试构建一个 'non-centralized' 图形结构,其中节点和边相互交叉。与此非常相似:Circular template reference structure.
尽管如此,我正在尝试支持节点可以包含多种不同 'arity' 类型的边。而且,反过来,边缘的许多节点类型。
¿有没有一种方法可以在不依赖继承的情况下通过泛型编程/元编程实现这一点?
我尝试的以下方法突出了问题:
#include <iostream>
#include <tuple>
#include <list>
using namespace std;
template<class ...EdgeTypes>
class node
{
public:
std::tuple<std::list<EdgeTypes*>...> edges_;
template<size_t I>
using container_value_type_i = typename std::tuple_element<I, decltype(edges_) >::type::value_type;
template< std::size_t I>
void addEdge(const container_value_type_i<I>& e)
{ std::get<I>(edges_).push_back(e); }
};
template<template<class...> class ...V>
class edge
{
public:
std::tuple<V<edge>*...> vertices_;
// ^^^^
// its forcing that all nodes have the same number of 'edges types' (one)
// and that they are of the same 'arity' as edge object
template<size_t I>
using vertex_type_i = typename std::tuple_element<I, decltype(vertices_) >::type;
template< std::size_t I>
void addNode(const vertex_type_i<I>& e)
{ std::get<I>(vertices_) = e; }
};
int main()
{
edge<node> unary_edge;
edge<node, node> binary_edge;
node<edge<node>> unary_node_of_unary_edges;
unary_node_of_unary_edges.addEdge<0>(&unary_edge);
unary_edge.addNode<0>(&unary_node_of_unary_edges);
node<edge<node, node>> unary_node_of_binary_edges;
unary_node_of_binary_edges.addEdge<0>(&binary_edge);
// This won't compile as edge type of node's edges are not the same as unary_edge
//unary_edge.addNode<0>(unary_node_of_binary_edges);
node<edge<node>, edge<node, node>> binary_node_of_unary_edges_and_binary_edges;
binary_node_of_unary_edges_and_binary_edges.addEdge<0>(&unary_edge);
binary_node_of_unary_edges_and_binary_edges.addEdge<1>(&binary_edge);
// This won't compile as nodes's edges are not all the same type
//unary_edge.addNode<0>(&binary_node_of_unary_edges_and_binary_edges);
return 0;
}
您可以在类型系统中对图形的整个空气结构进行编码,但我怀疑这是否有用。
类型擦除始终是一个选项。忽略这一点,您可以为边缘类型和节点类型以及最大通风度使用模板。
template<template<class...>class Z>
struct ztemplate{
template<class...Ts>
using z=Z<Ts...>;
};
template<class zE, class Indexes>
class Node;
using zNode=ztemplate<Node>;
template<class zN, class Indexes, class Count>
class Edge;
using zEdge=ztemplate<Edge>;
template<class zE, std::size_t...Is>
class Node<zE,std::index_sequence<Is...>>{
std::tuple< std::list< zE::template z<zNode, std::index_sequence<Is...>, std::integral_constant<std::size_t,Is>>... > edges;
};
template<class zN, std::size_t...Is, std::size_t A>
class Edge<zN,std::index_sequence<Is...>, std::integral_constant<std::size_t,A>>{
std::array< zN::template z<zEdge, std::index_sequence<Is...>>*, A> nodes;
};
或类似的东西。
我正在尝试构建一个 'non-centralized' 图形结构,其中节点和边相互交叉。与此非常相似:Circular template reference structure.
尽管如此,我正在尝试支持节点可以包含多种不同 'arity' 类型的边。而且,反过来,边缘的许多节点类型。
¿有没有一种方法可以在不依赖继承的情况下通过泛型编程/元编程实现这一点?
我尝试的以下方法突出了问题:
#include <iostream>
#include <tuple>
#include <list>
using namespace std;
template<class ...EdgeTypes>
class node
{
public:
std::tuple<std::list<EdgeTypes*>...> edges_;
template<size_t I>
using container_value_type_i = typename std::tuple_element<I, decltype(edges_) >::type::value_type;
template< std::size_t I>
void addEdge(const container_value_type_i<I>& e)
{ std::get<I>(edges_).push_back(e); }
};
template<template<class...> class ...V>
class edge
{
public:
std::tuple<V<edge>*...> vertices_;
// ^^^^
// its forcing that all nodes have the same number of 'edges types' (one)
// and that they are of the same 'arity' as edge object
template<size_t I>
using vertex_type_i = typename std::tuple_element<I, decltype(vertices_) >::type;
template< std::size_t I>
void addNode(const vertex_type_i<I>& e)
{ std::get<I>(vertices_) = e; }
};
int main()
{
edge<node> unary_edge;
edge<node, node> binary_edge;
node<edge<node>> unary_node_of_unary_edges;
unary_node_of_unary_edges.addEdge<0>(&unary_edge);
unary_edge.addNode<0>(&unary_node_of_unary_edges);
node<edge<node, node>> unary_node_of_binary_edges;
unary_node_of_binary_edges.addEdge<0>(&binary_edge);
// This won't compile as edge type of node's edges are not the same as unary_edge
//unary_edge.addNode<0>(unary_node_of_binary_edges);
node<edge<node>, edge<node, node>> binary_node_of_unary_edges_and_binary_edges;
binary_node_of_unary_edges_and_binary_edges.addEdge<0>(&unary_edge);
binary_node_of_unary_edges_and_binary_edges.addEdge<1>(&binary_edge);
// This won't compile as nodes's edges are not all the same type
//unary_edge.addNode<0>(&binary_node_of_unary_edges_and_binary_edges);
return 0;
}
您可以在类型系统中对图形的整个空气结构进行编码,但我怀疑这是否有用。
类型擦除始终是一个选项。忽略这一点,您可以为边缘类型和节点类型以及最大通风度使用模板。
template<template<class...>class Z>
struct ztemplate{
template<class...Ts>
using z=Z<Ts...>;
};
template<class zE, class Indexes>
class Node;
using zNode=ztemplate<Node>;
template<class zN, class Indexes, class Count>
class Edge;
using zEdge=ztemplate<Edge>;
template<class zE, std::size_t...Is>
class Node<zE,std::index_sequence<Is...>>{
std::tuple< std::list< zE::template z<zNode, std::index_sequence<Is...>, std::integral_constant<std::size_t,Is>>... > edges;
};
template<class zN, std::size_t...Is, std::size_t A>
class Edge<zN,std::index_sequence<Is...>, std::integral_constant<std::size_t,A>>{
std::array< zN::template z<zEdge, std::index_sequence<Is...>>*, A> nodes;
};
或类似的东西。