gpt4 book ai didi

c++ - 既是基类又可直接使用的类模板

转载 作者:行者123 更新时间:2023-11-30 02:16:27 28 4
gpt4 key购买 nike

我有两个表示图形的类:

class Node {
public:
void AppendSource(Edge &Edge) { m_Sources.append(&Edge); }
void AppendSink(Edge &Edge) { m_Sinks.append(&Edge); }
QList<Edge *> &Sources() { return m_Sources; }
QList<Edge *> &Sinks() { return m_Sinks; }
QList<Edge *> const &Sources() const { return m_Sources; }
QList<Edge *> const &Sinks() const { return m_Sinks; }
protected:
QList<Edge *> m_Sources;
QList<Edge *> m_Sinks;
}; // Node

class Edge {
public:
Edge(Node &Source, Node &Sink) : m_pSource(&Source), m_pSink(&Sink) {}
Node const &Source() const { return *m_pSource; }
Node const &Sink() const { return *m_pSink; }
Node &Source() { return *m_pSource; }
Node &Sink() { return *m_pSink; }
void SetSource(Node &Source) { m_pSource = &Source; }
void SetSink(Node &Sink) { m_pSink = &Sink; }
protected:
Node *m_pSource;
Node *m_pSink;
}; // Edge

应该可以继承这些类,以便为特定类型的图表添加功能。因此,这些类应该是模板类:

template <class EDGE_TYPE>
class Node {
public:
void AppendSource(EDGE_TYPE &Edge) { m_Sources.append(&Edge); }
void AppendSink(EDGE_TYPE &Edge) { m_Sinks.append(&Edge); }
QList<EDGE_TYPE *> &Sources() { return m_Sources; }
QList<EDGE_TYPE *> &Sinks() { return m_Sinks; }
QList<EDGE_TYPE *> const &Sources() const { return m_Sources; }
QList<EDGE_TYPE *> const &Sinks() const { return m_Sinks; }
protected:
QList<EDGE_TYPE *> m_Sources;
QList<EDGE_TYPE *> m_Sinks;
}; // Node


template <class NODE_TYPE>
class Edge {
public:
Edge(NODE_TYPE &Source, NODE_TYPE &Sink) : m_pSource(&Source), m_pSink(&Sink) {}
NODE_TYPE const &Source() const { return *m_pSource; }
NODE_TYPE const &Sink() const { return *m_pSink; }
NODE_TYPE &Source() { return *m_pSource; }
NODE_TYPE &Sink() { return *m_pSink; }
void SetSource(NODE_TYPE &Source) { m_pSource = &Source; }
void SetSink(NODE_TYPE &Sink) { m_pSink = &Sink; }
protected:
NODE_TYPE *m_pSource;
NODE_TYPE *m_pSink;
}; // Edge

但现在似乎不再可能在不扩展它们的情况下使用这些类!有明显相应错误的几次尝试:

new Node(); // 'Node': use of class template requires template argument list
new Node<>(); // 'Node': too few template arguments
new Node<Edge>(); // 'Edge': unspecialized class template can't be used as a template argument for template parameter 'EDGE_TYPE', expected a real type
new Node<Edge<>>(); // 'Edge': too few template arguments
new Node<Edge<Node>>(); // 'Node': unspecialized class template can't be used as a template argument for template parameter 'NODE_TYPE', expected a real type
new Node<Edge<Node<>>>(); // 'Node': too few template arguments

我希望通过为模板参数引入默认值来解决这个问题。一些带有相应错误的尝试:

template <class EDGE_TYPE = Edge>
class Node { ... }

template <class NODE_TYPE = Node>
class Edge { ... }

new Node<>(); // 'Edge': unspecialized class template can't be used as a template argument for template parameter 'EDGE_TYPE', expected a real type
template <class EDGE_TYPE = Edge<>>
class Node { ... }

template <class NODE_TYPE = Node<>>
class Edge { ... }

new Node<>(); // recursive type or function dependency context too complex
template <class EDGE_TYPE = Edge<Node<EDGE_TYPE>>>
class Node { ... }


template <class NODE_TYPE = Node<Edge<NODE_TYPE>>>
class Edge { ... }

new Node<>(); // 'EDGE_TYPE': undeclared identifier

如何使 NodeEdge 既可直接使用又可通过继承进行扩展?

最佳答案

How can I make Node and Edge both directly usable and extensible though inheritance?

我将以粗体显示该要求。

虽然您可以让 Edge 和 Node 的定义相互依赖,但是没有办法对 Edge 和 Node 进行重复的声明,因为这样的声明会产生无限模板递归:

Node<> = Node<Edge<>> = Node<Edge<Node<>>> = Node<EdgeNode<Edge<>>>> ...

所以,如果你想要 Edge<>Node<>要直接可用(即无需创建虚拟派生类即可实例化),那么您应该打破该递归。例如,通过同时制作 EdgeNode取决于一些第三个特征类:

// Forward declaration.
struct DefaultGraphTypes;

template <typename GraphTypes = DefaultGraphTypes>
struct Node;

template <typename GraphTypes = DefaultGraphTypes>
struct Edge;


// Traits class.
template <typename NodeT, typename EdgeT>
struct GraphTypes
{
// Could change this to 'using' in modern C++
typedef NodeT FinalNodeType;
typedef EdgeT FinalEdgeType;

// typedef MayBeSomeOtherParameters ...
};

struct DefaultGraphTypes
: public GraphTypes<Node<DefaultGraphTypes>, Edge<DefaultGraphTypes>>
{
};


// Implementation of graph classes.
template <typename GraphTypes>
struct Node
{
typedef typename GraphTypes::FinalNodeType FinalNodeType;
typedef typename GraphTypes::FinalEdgeType FinalEdgeType;

// ... Your implementation
};

template <typename GraphTypes>
struct Edge
{
typedef typename GraphTypes::FinalNodeType FinalNodeType;
typedef typename GraphTypes::FinalEdgeType FinalEdgeType;

// ... Your implementation
};


// User-derived types.
struct MyNode;
struct MyEdge;

struct MyNode
: public Node<GraphTypes<MyNode, MyEdge>>
{
// Something specific
};

struct MyEdge
: public Edge<GraphTypes<MyNode, MyEdge>>
{
// Something specific
};


// Test
int main()
{
Node<> n1;
Edge<> e1;

MyNode n2;
MyEdge e2;

return 0;
}

关于c++ - 既是基类又可直接使用的类模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54881086/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com