@@ -13,26 +13,33 @@ cpp! {{
1313 #include <queue>
1414 #include <vector>
1515 #include <functional>
16+ #include <ranges>
1617 #include <cstddef>
1718} }
1819
1920/// Workaround for missing generic support in the `overload!` macro.
2021pub type T = std:: ffi:: c_int ;
2122
2223/// Wrapper holding a heap-allocated C++ `std::priority_queue<int>` pointer.
23- ///
24- /// ### Limitations
25- ///
26- /// Only the default container and comparator are used, so constructors taking them are skipped.
2724#[ cfg_attr( not( test) , expect( dead_code, reason = "Only used in tests" ) ) ]
2825pub struct StdPriorityQueue ( * mut c_void , PhantomData < T > ) ;
2926
27+ pub struct StdLess ;
28+
3029#[ cfg_attr( not( test) , expect( dead_code, reason = "Only used in tests" ) ) ]
3130#[ allow(
3231 non_upper_case_globals,
3332 reason = "Triggered by cpp! macro in rust-analyzer"
3433) ]
3534impl StdPriorityQueue {
35+ fn as_ptr_or_null ( items : & [ T ] ) -> * const T {
36+ if items. is_empty ( ) {
37+ std:: ptr:: null ( )
38+ } else {
39+ items. as_ptr ( )
40+ }
41+ }
42+
3643 fn default ( ) -> StdPriorityQueue {
3744 let pq = unsafe {
3845 cpp ! ( [ ] -> * mut c_void as "std::priority_queue<int>*" {
@@ -42,12 +49,53 @@ impl StdPriorityQueue {
4249 StdPriorityQueue ( pq, PhantomData )
4350 }
4451
52+ fn from_compare ( _compare : & StdLess ) -> StdPriorityQueue {
53+ let pq = unsafe {
54+ cpp ! ( [ ] -> * mut c_void as "std::priority_queue<int>*" {
55+ return new std:: priority_queue<int>( std:: less<int>( ) ) ;
56+ } )
57+ } ;
58+ StdPriorityQueue ( pq, PhantomData )
59+ }
60+
61+ fn from_container_copy ( _compare : & StdLess , cont : & [ T ] ) -> StdPriorityQueue {
62+ let len = cont. len ( ) ;
63+ let cont: * const T = StdPriorityQueue :: as_ptr_or_null ( cont) ;
64+ let pq = unsafe {
65+ cpp ! ( [ cont as "const int*" , len as "size_t" ] -> * mut c_void as "std::priority_queue<int>*" {
66+ const std:: vector<int> container( cont, cont + len) ;
67+ return new std:: priority_queue<int>( std:: less<int>( ) , container) ;
68+ } )
69+ } ;
70+ StdPriorityQueue ( pq, PhantomData )
71+ }
72+
73+ fn from_container_move ( _compare : & StdLess , cont : Vec < T > ) -> StdPriorityQueue {
74+ let len = cont. len ( ) ;
75+ let cont: * const T = StdPriorityQueue :: as_ptr_or_null ( & cont) ;
76+ let pq = unsafe {
77+ cpp ! ( [ cont as "const int*" , len as "size_t" ] -> * mut c_void as "std::priority_queue<int>*" {
78+ std:: vector<int> container( cont, cont + len) ;
79+ return new std:: priority_queue<int>( std:: less<int>( ) , std:: move( container) ) ;
80+ } )
81+ } ;
82+ StdPriorityQueue ( pq, PhantomData )
83+ }
84+
4585 fn from_slice ( items : & [ T ] ) -> StdPriorityQueue {
46- if items. is_empty ( ) {
47- return StdPriorityQueue :: default ( ) ;
48- }
4986 let len = items. len ( ) ;
50- let items: * const T = items. as_ptr ( ) ;
87+ let items: * const T = StdPriorityQueue :: as_ptr_or_null ( items) ;
88+ let pq = unsafe {
89+ cpp ! ( [ items as "const int*" , len as "size_t" ] -> * mut c_void as "std::priority_queue<int>*" {
90+ return new std:: priority_queue<int>( items, items + len) ;
91+ } )
92+ } ;
93+ StdPriorityQueue ( pq, PhantomData )
94+ }
95+
96+ fn from_slice_with_compare ( items : & [ T ] , _compare : & StdLess ) -> StdPriorityQueue {
97+ let len = items. len ( ) ;
98+ let items: * const T = StdPriorityQueue :: as_ptr_or_null ( items) ;
5199 let pq = unsafe {
52100 cpp ! ( [ items as "const int*" , len as "size_t" ] -> * mut c_void as "std::priority_queue<int>*" {
53101 return new std:: priority_queue<int>( items, items + len, std:: less<int>( ) ) ;
@@ -56,20 +104,74 @@ impl StdPriorityQueue {
56104 StdPriorityQueue ( pq, PhantomData )
57105 }
58106
107+ fn from_slice_container_copy ( items : & [ T ] , _compare : & StdLess , cont : & [ T ] ) -> StdPriorityQueue {
108+ let len = items. len ( ) ;
109+ let items: * const T = StdPriorityQueue :: as_ptr_or_null ( items) ;
110+ let cont_len = cont. len ( ) ;
111+ let cont: * const T = StdPriorityQueue :: as_ptr_or_null ( cont) ;
112+ let pq = unsafe {
113+ cpp ! ( [ items as "const int*" , len as "size_t" , cont as "const int*" , cont_len as "size_t" ] -> * mut c_void as "std::priority_queue<int>*" {
114+ const std:: vector<int> container( cont, cont + cont_len) ;
115+ return new std:: priority_queue<int>( items, items + len, std:: less<int>( ) , container) ;
116+ } )
117+ } ;
118+ StdPriorityQueue ( pq, PhantomData )
119+ }
120+
121+ fn from_slice_container_move (
122+ items : & [ T ] ,
123+ _compare : & StdLess ,
124+ cont : Vec < T > ,
125+ ) -> StdPriorityQueue {
126+ let len = items. len ( ) ;
127+ let items: * const T = StdPriorityQueue :: as_ptr_or_null ( items) ;
128+ let cont_len = cont. len ( ) ;
129+ let cont: * const T = StdPriorityQueue :: as_ptr_or_null ( & cont) ;
130+ let pq = unsafe {
131+ cpp ! ( [ items as "const int*" , len as "size_t" , cont as "const int*" , cont_len as "size_t" ] -> * mut c_void as "std::priority_queue<int>*" {
132+ std:: vector<int> container( cont, cont + cont_len) ;
133+ return new std:: priority_queue<int>( items, items + len, std:: less<int>( ) , std:: move( container) ) ;
134+ } )
135+ } ;
136+ StdPriorityQueue ( pq, PhantomData )
137+ }
138+
59139 /// ### Limitations
60140 ///
61141 /// `overload!` can't take a generic iterator, so callers must cast to `&mut dyn Iterator`.
62- /// This also stands in for the C++23 `from_range` constructor, whose tag isn't needed in Rust.
142+ /// This stands in for the C++23 `from_range` constructor, whose tag isn't needed in Rust.
63143 fn from_iter ( iter : & mut dyn Iterator < Item = T > ) -> StdPriorityQueue {
64144 let items: Vec < T > = iter. collect ( ) ;
65- if items. is_empty ( ) {
66- return StdPriorityQueue :: default ( ) ;
67- }
68145 let len = items. len ( ) ;
69- let items: * const T = items . as_ptr ( ) ;
146+ let items: * const T = StdPriorityQueue :: as_ptr_or_null ( & items ) ;
70147 let pq = unsafe {
71148 cpp ! ( [ items as "const int*" , len as "size_t" ] -> * mut c_void as "std::priority_queue<int>*" {
72- return new std:: priority_queue<int>( items, items + len, std:: less<int>( ) ) ;
149+ std:: vector<int> vec( items, items + len) ;
150+ #ifdef __cpp_lib_containers_ranges
151+ return new std:: priority_queue<int>( std:: from_range, vec) ;
152+ #else
153+ #error "std::from_range is not available, try using `-std=c++23` or a newer compiler"
154+ #endif
155+ } )
156+ } ;
157+ StdPriorityQueue ( pq, PhantomData )
158+ }
159+
160+ fn from_iter_with_compare (
161+ iter : & mut dyn Iterator < Item = T > ,
162+ _compare : & StdLess ,
163+ ) -> StdPriorityQueue {
164+ let items: Vec < T > = iter. collect ( ) ;
165+ let len = items. len ( ) ;
166+ let items: * const T = StdPriorityQueue :: as_ptr_or_null ( & items) ;
167+ let pq = unsafe {
168+ cpp ! ( [ items as "const int*" , len as "size_t" ] -> * mut c_void as "std::priority_queue<int>*" {
169+ std:: vector<int> vec( items, items + len) ;
170+ #ifdef __cpp_lib_containers_ranges
171+ return new std:: priority_queue<int>( std:: from_range, vec, std:: less<int>( ) ) ;
172+ #else
173+ #error "std::from_range is not available, try using `-std=c++23` or a newer compiler"
174+ #endif
73175 } )
74176 } ;
75177 StdPriorityQueue ( pq, PhantomData )
@@ -182,14 +284,42 @@ overload! {
182284 StdPriorityQueue :: default ( )
183285 }
184286
287+ pub fn new( compare: & StdLess ) -> StdPriorityQueue {
288+ StdPriorityQueue :: from_compare( compare)
289+ }
290+
291+ pub fn new( compare: & StdLess , cont: & [ T ] ) -> StdPriorityQueue {
292+ StdPriorityQueue :: from_container_copy( compare, cont)
293+ }
294+
295+ pub fn new( compare: & StdLess , cont: Vec <T >) -> StdPriorityQueue {
296+ StdPriorityQueue :: from_container_move( compare, cont)
297+ }
298+
185299 pub fn new( items: & [ T ] ) -> StdPriorityQueue {
186300 StdPriorityQueue :: from_slice( items)
187301 }
188302
303+ pub fn new( items: & [ T ] , compare: & StdLess ) -> StdPriorityQueue {
304+ StdPriorityQueue :: from_slice_with_compare( items, compare)
305+ }
306+
307+ pub fn new( items: & [ T ] , compare: & StdLess , cont: & [ T ] ) -> StdPriorityQueue {
308+ StdPriorityQueue :: from_slice_container_copy( items, compare, cont)
309+ }
310+
311+ pub fn new( items: & [ T ] , compare: & StdLess , cont: Vec <T >) -> StdPriorityQueue {
312+ StdPriorityQueue :: from_slice_container_move( items, compare, cont)
313+ }
314+
189315 pub fn new( iter: & mut dyn Iterator <Item = T >) -> StdPriorityQueue {
190316 StdPriorityQueue :: from_iter( iter)
191317 }
192318
319+ pub fn new( iter: & mut dyn Iterator <Item = T >, compare: & StdLess ) -> StdPriorityQueue {
320+ StdPriorityQueue :: from_iter_with_compare( iter, compare)
321+ }
322+
193323 pub fn new( other: & StdPriorityQueue ) -> StdPriorityQueue {
194324 StdPriorityQueue :: copy_from( other)
195325 }
@@ -214,6 +344,11 @@ overload! {
214344
215345overload ! {
216346 impl StdPriorityQueue {
347+ /// ### Limitations
348+ ///
349+ /// `self` is ignored when picking overloads, the macro only looks at the other arguments.
350+ /// Constructor argument types that end up as the same Rust type will clash (`long` and `long long` are both `i64`, for example).
351+ /// `int` is fine, no conflict there.
217352 pub fn emplace( & mut self ) {
218353 self . emplace_default( )
219354 }
@@ -231,19 +366,65 @@ pub fn test_priority_queue() {
231366 assert_eq ! ( default_pq. len( ) , 0 ) ;
232367 assert_eq ! ( default_pq. top_const( ) , None ) ;
233368
369+ let from_compare = StdPriorityQueue :: new ( & StdLess ) ;
370+ assert ! ( from_compare. is_empty( ) ) ;
371+
372+ let from_container_copy = StdPriorityQueue :: new ( & StdLess , [ 3 , 1 , 4 ] . as_slice ( ) ) ;
373+ assert_eq ! ( from_container_copy. top_const( ) , Some ( & 4 ) ) ;
374+ assert_eq ! ( from_container_copy. len( ) , 3 ) ;
375+ let from_empty_container_copy = StdPriorityQueue :: new ( & StdLess , [ ] . as_slice ( ) ) ;
376+ assert ! ( from_empty_container_copy. is_empty( ) ) ;
377+
378+ let from_container_move = StdPriorityQueue :: new ( & StdLess , vec ! [ 3 , 1 , 4 ] ) ;
379+ assert_eq ! ( from_container_move. top_const( ) , Some ( & 4 ) ) ;
380+ assert_eq ! ( from_container_move. len( ) , 3 ) ;
381+ let from_empty_container_move = StdPriorityQueue :: new ( & StdLess , Vec :: new ( ) ) ;
382+ assert ! ( from_empty_container_move. is_empty( ) ) ;
383+
234384 let from_slice: StdPriorityQueue = StdPriorityQueue :: new ( [ 3 , 1 , 4 , 1 , 5 ] . as_slice ( ) ) ;
235385 assert_eq ! ( from_slice. top_const( ) , Some ( & 5 ) ) ;
236386 assert_eq ! ( from_slice. len( ) , 5 ) ;
237387 let from_empty_slice = StdPriorityQueue :: new ( [ ] . as_slice ( ) ) ;
238388 assert ! ( from_empty_slice. is_empty( ) ) ;
239389
390+ let from_slice_with_compare = StdPriorityQueue :: new ( [ 3 , 1 , 4 ] . as_slice ( ) , & StdLess ) ;
391+ assert_eq ! ( from_slice_with_compare. top_const( ) , Some ( & 4 ) ) ;
392+ let from_empty_slice_with_compare = StdPriorityQueue :: new ( [ ] . as_slice ( ) , & StdLess ) ;
393+ assert ! ( from_empty_slice_with_compare. is_empty( ) ) ;
394+
395+ let from_slice_container_copy =
396+ StdPriorityQueue :: new ( [ 5 , 2 ] . as_slice ( ) , & StdLess , [ 9 , 1 ] . as_slice ( ) ) ;
397+ assert_eq ! ( from_slice_container_copy. top_const( ) , Some ( & 9 ) ) ;
398+ assert_eq ! ( from_slice_container_copy. len( ) , 4 ) ;
399+ let from_empty_slice_container_copy =
400+ StdPriorityQueue :: new ( [ ] . as_slice ( ) , & StdLess , [ ] . as_slice ( ) ) ;
401+ assert ! ( from_empty_slice_container_copy. is_empty( ) ) ;
402+
403+ let from_slice_container_move = StdPriorityQueue :: new ( [ 5 , 2 ] . as_slice ( ) , & StdLess , vec ! [ 9 , 1 ] ) ;
404+ assert_eq ! ( from_slice_container_move. top_const( ) , Some ( & 9 ) ) ;
405+ assert_eq ! ( from_slice_container_move. len( ) , 4 ) ;
406+ let from_empty_slice_container_move =
407+ StdPriorityQueue :: new ( [ ] . as_slice ( ) , & StdLess , Vec :: new ( ) ) ;
408+ assert ! ( from_empty_slice_container_move. is_empty( ) ) ;
409+
240410 let mut iter: std:: array:: IntoIter < T , 3 > = [ 10 , 20 , 30 ] . into_iter ( ) ;
241411 let from_iter = StdPriorityQueue :: new ( & mut iter as & mut dyn Iterator < Item = _ > ) ;
242412 assert_eq ! ( from_iter. top_const( ) , Some ( & 30 ) ) ;
243413 let mut empty_iter: std:: array:: IntoIter < T , 0 > = [ ] . into_iter ( ) ;
244414 let from_empty_iter = StdPriorityQueue :: new ( & mut empty_iter as & mut dyn Iterator < Item = _ > ) ;
245415 assert ! ( from_empty_iter. is_empty( ) ) ;
246416
417+ let mut compare_iter: std:: array:: IntoIter < T , 3 > = [ 10 , 20 , 30 ] . into_iter ( ) ;
418+ let from_iter_with_compare =
419+ StdPriorityQueue :: new ( & mut compare_iter as & mut dyn Iterator < Item = _ > , & StdLess ) ;
420+ assert_eq ! ( from_iter_with_compare. top_const( ) , Some ( & 30 ) ) ;
421+ let mut empty_compare_iter: std:: array:: IntoIter < T , 0 > = [ ] . into_iter ( ) ;
422+ let from_empty_iter_with_compare = StdPriorityQueue :: new (
423+ & mut empty_compare_iter as & mut dyn Iterator < Item = _ > ,
424+ & StdLess ,
425+ ) ;
426+ assert ! ( from_empty_iter_with_compare. is_empty( ) ) ;
427+
247428 let ref_clone = StdPriorityQueue :: new ( & from_slice) ;
248429 assert_eq ! ( ref_clone. top_const( ) , Some ( & 5 ) ) ;
249430 assert_eq ! ( ref_clone. len( ) , 5 ) ;
0 commit comments