具有const成员的对象上的优先级队列比较器

heu*_*cus 4 c++ libstdc++ c++11

我正在尝试实现一个优先级队列,该队列使用一个具有const成员的对象,该成员用于定义队列中对象的优先级.以下是我正在使用的精简版本

#include <vector>
#include <queue>

class Event {
public:
    Event(float _time) : time(_time) {};
    const float time;
};

struct EventComp {
public:
    bool operator()(const Event& a, const Event& b) const {
      return a.time < b.time;
    }
};

class EventQueue {
private:
    std::priority_queue<Event, std::vector<Event>, EventComp> events;
};


int main(int argc, char *argv[])
{
    EventQueue q;
}
Run Code Online (Sandbox Code Playgroud)

当我尝试编译时(使用g ++ -std = c ++ 11),我收到以下错误消息,我不太明白.

g++ -std=c++11 events.cpp -o events
In file included from /usr/include/c++/4.8/queue:62:0,
                 from events.cpp:2:
/usr/include/c++/4.8/bits/stl_heap.h: In instantiation of ‘void std::__adjust_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Event*, std::vector<Event> >; _Distance = long int; _Tp = Event; _Compare = EventComp]’:
/usr/include/c++/4.8/bits/stl_heap.h:448:15:   required from ‘void std::make_heap(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Event*, std::vector<Event> >; _Compare = EventComp]’
/usr/include/c++/4.8/bits/stl_queue.h:411:48:   required from ‘std::priority_queue<_Tp, _Sequence, _Compare>::priority_queue(const _Compare&, _Sequence&&) [with _Tp = Event; _Sequence = std::vector<Event>; _Compare = EventComp]’
events.cpp:15:7:   required from here
/usr/include/c++/4.8/bits/stl_heap.h:315:29: error: use of deleted function ‘Event& Event::operator=(Event&&)’
    *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
                             ^
events.cpp:4:7: note: ‘Event& Event::operator=(Event&&)’ is implicitly deleted because the default definition would be ill-formed:
 class Event {
       ^
events.cpp:4:7: error: non-static const member ‘const float Event::time’, can’t use default assignment operator
In file included from /usr/include/c++/4.8/queue:62:0,
                 from events.cpp:2:
/usr/include/c++/4.8/bits/stl_heap.h:321:29: error: use of deleted function ‘Event& Event::operator=(Event&&)’
    *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
                             ^
Run Code Online (Sandbox Code Playgroud)

我假设内部结构的某些部分priority_queue需要移动赋值运算符来插入元素,但该const成员似乎阻止了该运算符的定义.我尝试使用五的规则,但它似乎没有成功.我需要在类定义中添加什么才能使其正常工作?

编辑:我知道,我可以删除const从成员变量预选赛,使它private,并添加一个访问成员函数来获取变量的值,但我宁愿把它publicconst,让我感兴趣的解决方案,保持成员变量在示例中(如果可能的话).

How*_*ant 7

std::priority_queue<Event, ...>要求的默认构造函数EventMoveAssignable因为它调用std::make_heap(具有此要求). Event不是MoveAssignable因为const float time数据成员.如果const从此数据成员中删除限定符,则应编译代码.

我知道,我可以删除const从成员变量预选赛,使它private,并添加一个访问成员函数来获取变量的值,但我宁愿把它publicconst,所以我很感兴趣,其中保留解决方案成员变量就像在示例中一样(如果可能的话).

最后,使用该标准:: LIB设施,EventMoveAssignable.可以使用移动赋值运算符或复制赋值运算符来满足此要求.这些中的任何一个或两个都可以由您或编译器提供.但是当你有一个const数据成员时,编译器提供的特殊成员将被隐式删除.

如果您愿意,请继续提供您自己的副本和/或移动分配操作符:

class Event {
public:
    Event(float _time) : time(_time) {};
    const float time;

    Event(Event&&) = default;
    Event& operator=(Event&&);  // Supply this
};
Run Code Online (Sandbox Code Playgroud)

我没有一个很好的猜测,你可能想移动(或复制)赋值运算符的事,因为你已经表示,一旦建造什么,你不希望time永远改变.这是一个必须解决的设计决策(并且与C++语法相比,更多地与软件设计有关).


<aside>

在问题的评论中,POW注意到问题中的代码用clang编译(更准确地说,用libc ++).这样做的原因是libc ++中几乎符合要求的扩展:

该标准指定了这个priority_queue构造函数:

explicit priority_queue(const Compare& x = Compare(),
                        Container&& c = Container());
Run Code Online (Sandbox Code Playgroud)

std::make_heap用容器调用c.但该标准还为实现者提供了余地,以使用默认值替换成员函数签名,并具有等效的重载.libc ++用以下三个替换此单个签名:

priority_queue();
explicit priority_queue(const Compare& x);
explicit priority_queue(const Compare& x, Container&& c);
Run Code Online (Sandbox Code Playgroud)

只有第三个需要打电话std::make_heap.因此,libc ++中的默认构造函数对它的要求较少value_type.

我说差点顺从.不完全符合的部分是未声明默认构造函数explicit.这是一个有意识的设计决策,使实现者priority_queue更容易使用.

</aside>