让虚方法接受任何 Qt 容器类型作为输入参数
Let virtual method accept any Qt container type as input paramter
我有两个图表 类:DirectedGraph
和 DirectedBreakableGraph
。 DirectedBreakableGraph
继承自 DirectedGraph
,并提供暂时 断开 边的能力,这意味着不应遍历它们,即使它们仍然是图的一部分。这样可以暂时解决图中的循环
DirectedGraph
有一个DFS
(深度优先搜索)遍历图的方法。此方法是 virtual
,因此 DirectedBreakableGraph
可以有自己的实现,忽略断边。
我希望能够通过将起始节点集合传递给 DFS
来指定深度优先搜索应该从哪个节点开始。现在,我不想限制包含起始节点的集合的类型。例如,它可以是 QVector
或 QSet
.
由于方法是虚拟的,所以它不能同时是模板。那么是否不可能让它同时接受 QVector
和 QSet
作为输入参数?也许除了使用 type erasure?
class DirectedGraph {
public:
// DFS should accept either QVector or QSet.
virtual void DFS(QVector<Node *> const &StartNodes) const;
};
class DirectedBreakableGraph : public DirectedGraph {
public:
// DFS should accept either QVector or QSet.
void DFS(QVector<Node *> const &StartNodes) const override;
};
使用类型擦除,您可能会执行以下操作:
template <typename T>
struct IGenerator
{
virtual ~IGenerator() = default;
virtual void reset() = 0;
virtual const T* value_and_next() = 0;
};
template <typename Container>
struct Generator : IGenerator<typename Container::value_type>
{
Generator(const Container& container) : container(container), it(container.begin()) {}
virtual void reset() override { it = container.begin(); }
virtual const typename Container::value_type* value_and_next() override
{
if (it == container) { return nullptr; }
return &(*it++);
}
const Container& container;
typename Container::const_iterator it;
};
class DirectedGraph {
public:
// DFS should accept either QVector or QSet.
virtual void DFS(IGenerator<Node *> const &StartNodes) const
{
while (const auto* p = StartNodes.value_and_next()) {
Node* node = *p;
// ...
}
}
};
然后你可能会做
directGraph.DFS(Generator{myVector});
directGraph.DFS(Generator{mySet});
我有两个图表 类:DirectedGraph
和 DirectedBreakableGraph
。 DirectedBreakableGraph
继承自 DirectedGraph
,并提供暂时 断开 边的能力,这意味着不应遍历它们,即使它们仍然是图的一部分。这样可以暂时解决图中的循环
DirectedGraph
有一个DFS
(深度优先搜索)遍历图的方法。此方法是 virtual
,因此 DirectedBreakableGraph
可以有自己的实现,忽略断边。
我希望能够通过将起始节点集合传递给 DFS
来指定深度优先搜索应该从哪个节点开始。现在,我不想限制包含起始节点的集合的类型。例如,它可以是 QVector
或 QSet
.
由于方法是虚拟的,所以它不能同时是模板。那么是否不可能让它同时接受 QVector
和 QSet
作为输入参数?也许除了使用 type erasure?
class DirectedGraph {
public:
// DFS should accept either QVector or QSet.
virtual void DFS(QVector<Node *> const &StartNodes) const;
};
class DirectedBreakableGraph : public DirectedGraph {
public:
// DFS should accept either QVector or QSet.
void DFS(QVector<Node *> const &StartNodes) const override;
};
使用类型擦除,您可能会执行以下操作:
template <typename T>
struct IGenerator
{
virtual ~IGenerator() = default;
virtual void reset() = 0;
virtual const T* value_and_next() = 0;
};
template <typename Container>
struct Generator : IGenerator<typename Container::value_type>
{
Generator(const Container& container) : container(container), it(container.begin()) {}
virtual void reset() override { it = container.begin(); }
virtual const typename Container::value_type* value_and_next() override
{
if (it == container) { return nullptr; }
return &(*it++);
}
const Container& container;
typename Container::const_iterator it;
};
class DirectedGraph {
public:
// DFS should accept either QVector or QSet.
virtual void DFS(IGenerator<Node *> const &StartNodes) const
{
while (const auto* p = StartNodes.value_and_next()) {
Node* node = *p;
// ...
}
}
};
然后你可能会做
directGraph.DFS(Generator{myVector});
directGraph.DFS(Generator{mySet});