我正在尝试编写一个从根节点开始搜索树中节点的程序。因为我希望搜索算法尽可能通用,所以我想使用模板,并且想使用SFINAE来检查给定类型是否实现了我需要的所有功能。
要计算节点的后继者,节点的类型必须具有函数successors()
,该函数返回节点的向量:
#import <vector>
class has_successors_t {
public:
virtual std::vector<has_successors_t> successors() = 0;
};
进行搜索的类如下:
#include <type_traits>
template <class node_t,
class = std::enable_if_t<std::is_base_of<has_successors_t, node_t>::value>>
class breadthFirstSearch {
public:
static node_t search(node_t root_node) {
// search for the target node
}
};
这样,仅当给定类型具有计算其后继函数的功能时,我才尝试使程序编译。但是,当我尝试执行以下操作时:
#import <vector>
class some_node_t : public has_successors_t {
public:
std::vector<some_node_t> successors() {
// return the successors
}
};
我收到一个错误:error: invalid covariant return type for 'virtual std::vector<some_node_t> some_node_t::successors()'
。
所以,我知道错误的含义,但是如何解决这样的问题?我可以想象,我不是第一个遇到具有基类和派生类的问题的人,并且我希望派生类中的重写函数返回一个向量(或数组,队列或类似的东西)其中包含派生类的元素。但是我只是找不到解决方案。
提前感谢您的帮助!
问候,塞巴斯蒂安
您可能可以使用CRTP实现类似的功能。
template <typename S>
class has_successors_t {
public:
virtual
std::vector<S> successors() = 0;
};
class some_node_t : public has_successors_t<some_node_t> {
public:
std::vector<some_node_t>
successors() {
// return the successors
}
};
然而,这意味着您将需要处理has_successors_t<some_node_t> *
,而不仅仅是has_successors_t *
。这就引出了下一个问题。如果您已经有了has_successors_t<some_node_t> *
,为什么不更进一步,只剩下some_node_t *
和沟has_successors_t
?
CRTP有一些用途,但您需要亲自查看它是否适合您的设计。