2014-12-27 66 views
4

我想實現一個優先級隊列,它使用一個具有用於定義隊列中對象的優先級的const成員的對象。以下是我使用的是什麼具有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; 
} 

當我嘗試編譯的精簡版(使用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 
          ^

我假定priority_queue的內部結構的一些部分需要移動賦值運算符插入元素,但const構件似乎防止操作者被定義。我試着用五條規則,但似乎沒有解決。我需要添加到類定義才能使其工作?

編輯:我知道,我可以從成員變量去除const預選賽中,使其private,並添加一個訪問成員函數來獲取變量的值,但我寧願把它publicconst,所以我對保持成員變量的解決方案很感興趣(如果甚至可以的話)。

+0

FWIW其上[_'clang'_]作品(http://rextester.com/CULSS5171) – P0W 2014-12-27 18:31:45

+0

來縮小問題看是否'矢量'編譯 – bolov 2014-12-27 18:32:54

+4

一些'VECTOR'的和'priority_queue'操作需要'MoveAssignable'。在你使用'const'數據成員的情況下,幾乎沒有辦法給它明智的賦值語義。使'time'非常量,如果你想避免修改,請將其設爲private,並提供一個getter。 – 2014-12-27 18:36:59

回答

7

std::priority_queue<Event, ...>默認的構造函數需要EventMoveAssignable,因爲它調用std::make_heap(有此要求)。由於const float time數據成員,因此Event不是MoveAssignable。如果從該數據成員中刪除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 
}; 

我沒有一個很好的猜測,你可能想招什麼(或複製)賦值運算符那麼,既然你已經說過,一旦建成,你不想time永遠不會改變。這是一個您必須制定的設計決策(並且通常與軟件設計有關,而不是C++語法)。


<aside>

在問題POW音符,在問題的代碼與編譯鐺的評論(更準確地,與libc++)。這樣做的原因是在libc中一個符合擴展++:

本標準規定了此priority_queue構造:

explicit priority_queue(const Compare& x = Compare(), 
         Container&& c = Container()); 

這就要求std::make_heap與容器c。但是該標準還給實施者提供了一些餘地,以便使用默認值替換成員函數簽名,並具有相同的重載。的libC++以下三個替換該單簽名:

priority_queue(); 
explicit priority_queue(const Compare& x); 
explicit priority_queue(const Compare& x, Container&& c); 

而且只有3需要調用std::make_heap。因此,libC++中的默認構造函數對value_type的要求較少。

我說將近符合。不完全符合的部分是默認構造函數未聲明爲explicit。這是實現者有意識地設計決策以使priority_queue更易於使用。

</aside>

+0

嗯,你確定將容器適配器的默認ctor設置爲'explicit'不是缺陷嗎?在DR中固定之前,容器默認ctors也是「顯式」的。 – 2014-12-27 23:42:29

+0

OTOH,他們沒有'initializer_list'構造函數,我猜爲什麼[LWG 2193](http://cplusplus.github.io/LWG/lwg-defects.html#2193)跳過了它們。 – 2014-12-27 23:47:07

+0

@ T.C .:我確定它*是一個缺陷。目前尚未有報道。 ;-) – 2014-12-27 23:48:25