集合比较器的正向声明
Forward declaration of set Comparator
我有一个使用节点(顶点(的图结构,而节点又以std::pair<Node*, int>
的形式附加了边,其中节点是边的另一端,整数是边权重。我想根据连接的节点索引和边权重将边按std::multiset
排序。
enum color { white, grey, black };
struct EdgeComparator;
struct Node {
int n;
std::multiset<std::pair<Node *, int>, EdgeComparator> edges;
enum color col;
int d; // distance to source node
explicit Node(int n) : n(n), edges(), col(white), d() {};
};
struct EdgeComparator {
bool operator()(const std::pair<Node *, int> &p1,
const std::pair<Node *, int> &p2) {
if (p1.second == p2.second)
return p1.first->n < p2.first->n;
return p1.second < p2.second;
}
};
这种前向声明方法会导致错误:invalid use of incomplete type struct EdgeComparator
。如果我尝试切换它们并向前声明 Node 而不是 EdgeComparator,那么 EdgeComparator 的n
字段不再可见,所以我遇到了恶性循环。
我想到的唯一解决方法是使用std::vector
而不是std::multiset
,然后应用std::sort
,但这在效率方面会非常昂贵,所以我想知道是否有另一种方法。
你可以这样做:
#include <set>
enum color { white, grey, black };
struct Node;
struct EdgeComparator {
bool operator()(const std::pair<Node *, int> &p1,
const std::pair<Node *, int> &p2);
};
struct Node {
int n;
std::multiset<std::pair<Node *, int>, EdgeComparator> edges;
enum color col;
int d; // distance to source node
explicit Node(int n) : n(n), edges(), col(white), d() {};
};
bool EdgeComparator::operator()(const std::pair<Node *, int> &p1,
const std::pair<Node *, int> &p2) {
if (p1.second == p2.second)
return p1.first->n < p2.first->n;
return p1.second < p2.second;
}
这在我这边编译得很好。原因是,您将声明和定义分开。EdgeComparator::operator(( 的定义需要具体的结构 Node,声明不需要,它只需要知道具有该名称的结构的存在:
- 向前声明节点为结构(声明 EdgeComparator 需要(
- 声明 EdgeComparator 而不定义运算符 (( (它需要知道成员 Node::n(
- 声明和定义节点
- 定义边缘比较器::运算符((
EdgeComparator
成为模板参数。
首先,它解决了你的情况。其次,它是有意义的,并允许您提供另一种类型的比较器。
template<class TEdgeComparator>
struct Node {
int n;
std::multiset<std::pair<Node *, int>, TEdgeComparator> edges;
// ...
};
struct EdgeComparator {
bool operator()(const std::pair<Node *, int> &p1,
const std::pair<Node *, int> &p2) {
if (p1.second == p2.second)
return p1.first->n < p2.first->n;
return p1.second < p2.second;
}
};
Node<EdgeComparator> myNode(42);
但请记住,拥有一个包含边缘集合的节点是一个危险信号。你确定你的设计吗?
相关文章:
- std::设置自定义比较器
- C++中"std::sort"比较器的不同类型
- 将 std::set 与基于键的比较器一起使用
- 带自定义比较器的最小优先级队列
- 函数类作为比较器
- 优先级队列自定义比较器
- 什么是自定义比较器以及如何在 C++ 的排序函数中使用它?
- 没有默认构造函数作为模板参数的自定义比较器
- set_intersection使用自定义设置比较器
- 如何为集合 c++ 建立比较器
- C++复杂情况的比较器通过参数问题
- 对于BTreeMap和其他依赖于Ord的东西,是否有等效于C++比较器对象?
- 对没有比较器或λ函数的向量进行排序?
- "operator()"在重载运算符方法中是什么意思,在priority_queue(STL)中用作C++中的比较器?
- 用户定义的结构是否有默认C++比较器?
- 集合比较器的正向声明
- 未在范围内声明 - priority_queue C++的友元比较器类
- 如何使用初始数据和自定义比较器声明 stl::p riority_queue
- 使用自定义比较器声明C++优先级队列的问题
- 如何在c++中声明带有指针类型比较器的set