//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME // // template // priority_queue(Compare, Container) // -> priority_queue; // // template::value_type>, // class Container = vector::value_type>> // priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) // -> priority_queue::value_type, Container, Compare>; // // template // priority_queue(Compare, Container, Allocator) // -> priority_queue; // // template>> // priority_queue(from_range_t, R&&, Compare = Compare()) // -> priority_queue, vector>, Compare>; // C++23 // // template // priority_queue(from_range_t, R&&, Compare, Allocator) // -> priority_queue, vector, Allocator>, // Compare>; // C++23 // // template // priority_queue(from_range_t, R&&, Allocator) // -> priority_queue, vector, Allocator>>; // C++23 #include #include // INT_MAX #include #include #include #include #include "deduction_guides_sfinae_checks.h" #include "test_macros.h" #include "test_iterators.h" #include "test_allocator.h" struct A {}; int main(int, char**) { // Test the explicit deduction guides { std::vector v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::priority_queue pri(std::greater(), v); // priority_queue(Compare, Container) static_assert(std::is_same_v, std::greater>>, ""); assert(pri.size() == v.size()); assert(pri.top() == 0); } { std::vector> v{10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; std::priority_queue pri(std::greater(), v, test_allocator(2)); // priority_queue(Compare, Container, Allocator) static_assert(std::is_same_v>, std::greater>>, ""); assert(pri.size() == v.size()); assert(pri.top() == 10); } { std::vector v{10, 11, 12, 13, 14, 15, 28, 17, 18, 19 }; std::priority_queue pri(v.begin(), v.end()); // priority_queue(Iter, Iter) static_assert(std::is_same_v>, ""); assert(pri.size() == v.size()); assert(pri.top() == 28); } { std::vector v{10, 11, 12, 13, 6, 15, 28, 17, 18, 19 }; std::priority_queue pri(v.begin(), v.end(), std::greater()); // priority_queue(Iter, Iter, Comp) static_assert(std::is_same_v, std::greater>>, ""); assert(pri.size() == v.size()); assert(pri.top() == 6); } { std::vector v{10, 6, 15, 28, 4, 18, 19 }; std::deque deq; std::priority_queue pri(v.begin(), v.end(), std::greater(), deq); // priority_queue(Iter, Iter, Comp, Container) static_assert(std::is_same_v, std::greater>>, ""); assert(pri.size() == v.size()); assert(pri.top() == 4); } // Test the implicit deduction guides { // We don't expect this one to work - no way to implicitly get value_type // std::priority_queue pri(std::allocator()); // queue (allocator &) } { std::priority_queue source; std::priority_queue pri(source); // priority_queue(priority_queue &) static_assert(std::is_same_v, ""); static_assert(std::is_same_v>, ""); assert(pri.size() == 0); } { typedef short T; typedef std::greater Comp; typedef test_allocator Alloc; typedef std::deque Cont; typedef test_allocator ConvertibleToAlloc; static_assert(std::uses_allocator_v && !std::is_same_v); { Comp comp; Cont cont; std::priority_queue pri(comp, cont, Alloc(2)); static_assert(std::is_same_v>); } { Comp comp; Cont cont; std::priority_queue pri(comp, cont, ConvertibleToAlloc(2)); static_assert(std::is_same_v>); } { Comp comp; Cont cont; std::priority_queue pri(comp, std::move(cont), Alloc(2)); static_assert(std::is_same_v>); } { Comp comp; Cont cont; std::priority_queue pri(comp, std::move(cont), ConvertibleToAlloc(2)); static_assert(std::is_same_v>); } } { typedef short T; typedef signed char ConvertibleToT; typedef std::greater Comp; typedef test_allocator Alloc; typedef std::deque Cont; typedef test_allocator ConvertibleToAlloc; static_assert(std::uses_allocator_v && !std::is_same_v); { std::priority_queue source; std::priority_queue pri(source, Alloc(2)); static_assert(std::is_same_v>); } { std::priority_queue source; std::priority_queue pri(source, ConvertibleToAlloc(2)); static_assert(std::is_same_v>); } { std::priority_queue source; std::priority_queue pri(std::move(source), Alloc(2)); static_assert(std::is_same_v>); } { std::priority_queue source; std::priority_queue pri(std::move(source), ConvertibleToAlloc(2)); static_assert(std::is_same_v>); } { Cont cont; std::priority_queue pri(Comp(), cont, Alloc(2)); static_assert(std::is_same_v>); } { Cont cont; std::priority_queue pri(Comp(), cont, ConvertibleToAlloc(2)); static_assert(std::is_same_v>); } { Cont cont; std::priority_queue pri(Comp(), std::move(cont), Alloc(2)); static_assert(std::is_same_v>); } { Cont cont; std::priority_queue pri(Comp(), std::move(cont), ConvertibleToAlloc(2)); static_assert(std::is_same_v>); } { T a[2] = {}; std::priority_queue pri(a, a+2, Alloc(2)); static_assert(std::is_same_v>>); } { T a[2] = {}; std::priority_queue pri(a, a+2, Comp(), Alloc(2)); static_assert(std::is_same_v, Comp>>); } { Cont cont; ConvertibleToT a[2] = {}; std::priority_queue pri(a, a+2, Comp(), cont, Alloc(2)); static_assert(std::is_same_v>); } { Cont cont; ConvertibleToT a[2] = {}; std::priority_queue pri(a, a+2, Comp(), cont, ConvertibleToAlloc(2)); static_assert(std::is_same_v>); } { Cont cont; ConvertibleToT a[2] = {}; std::priority_queue pri(a, a+2, Comp(), std::move(cont), Alloc(2)); static_assert(std::is_same_v>); } { Cont cont; ConvertibleToT a[2] = {}; std::priority_queue pri(a, a+2, Comp(), std::move(cont), ConvertibleToAlloc(2)); static_assert(std::is_same_v>); } #if TEST_STD_VER >= 23 { // (from_range, range) std::priority_queue c(std::from_range, Cont()); static_assert(std::is_same_v>); } { // (from_range, range, compare) std::priority_queue c(std::from_range, Cont(), Comp()); static_assert(std::is_same_v, Comp>>); } { // (from_range, range, compare, alloc) std::priority_queue c(std::from_range, Cont(), Comp(), Alloc(2)); static_assert(std::is_same_v, Comp>>); } { // (from_range, range, alloc) std::priority_queue c(std::from_range, Cont(), Alloc(2)); static_assert(std::is_same_v>>); } #endif // TEST_STD_VER >= 23 } // Deduction guides should be SFINAE'd away when given: // - "bad" input iterators (that is, a type not qualifying as an input // iterator); // - a bad allocator; // - an allocator instead of a comparator; // - an allocator instead of a container; // - an allocator and a container that uses a different allocator. { using Comp = std::less; using Cont = std::vector; using Alloc = std::allocator; using Iter = int*; // The only requirement in the Standard is that integral types cannot be // considered input iterators, beyond that it is unspecified. using BadIter = int; #ifdef _LIBCPP_VERSION struct OutputIter { using iterator_category = std::output_iterator_tag; using value_type = void; using difference_type = void; using pointer = void; using reference = void; const OutputIter& operator*() const { return *this; } const OutputIter& operator++() { return *this; } OutputIter operator++(int) const { return *this; } }; #endif // _LIBCPP_VERSION struct BadAlloc {}; using AllocAsComp = Alloc; using AllocAsCont = Alloc; using DiffAlloc = test_allocator; // (iter, iter) // // Cannot deduce from (BAD_iter, BAD_iter) static_assert(SFINAEs_away); // Note: (OutputIter, OutputIter) is interpreted as (comp, cont) and fails on accessing // non-existent typedefs in `OutputIter` (as if it were a container). There is no // requirement to SFINAE away bad containers. // (iter, iter, comp) // // Cannot deduce from (BAD_iter, BAD_iter, comp) static_assert(SFINAEs_away); LIBCPP_STATIC_ASSERT(SFINAEs_away); // Note: (iter, iter, ALLOC_as_comp) is allowed -- it just calls (iter, iter, alloc). // (iter, iter, comp, cont) // // Cannot deduce from (BAD_iter, BAD_iter, comp, cont) static_assert(SFINAEs_away); LIBCPP_STATIC_ASSERT(SFINAEs_away); // Cannot deduce from (iter, iter, ALLOC_as_comp, cont) static_assert(SFINAEs_away); // Note: (iter, iter, comp, ALLOC_as_cont) is allowed -- it just calls (iter, iter, comp, // alloc). // (iter, iter, alloc) // // Cannot deduce from (BAD_iter, BAD_iter, alloc) static_assert(SFINAEs_away); LIBCPP_STATIC_ASSERT(SFINAEs_away); // Note: (iter, iter, BAD_alloc) is interpreted as (iter, iter, comp) instead and fails upon // instantiation. There is no requirement to SFINAE away bad comparators. // (iter, iter, comp, alloc) // // Cannot deduce from (iter, iter, ALLOC_as_comp, alloc) static_assert(SFINAEs_away); // Note: (iter, iter, comp, BAD_alloc) is interpreted as (iter, iter, comp, cont) instead // and fails upon instantiation. There is no requirement to SFINAE away bad containers. // (iter, iter, comp, cont, alloc) // // Cannot deduce from (BAD_iter, BAD_iter, comp, cont, alloc) static_assert(SFINAEs_away); LIBCPP_STATIC_ASSERT( SFINAEs_away); // Cannot deduce from (iter, iter, ALLOC_as_comp, cont, alloc) static_assert(SFINAEs_away); // Cannot deduce from (iter, iter, comp, ALLOC_as_cont, alloc) static_assert(SFINAEs_away); // Cannot deduce from (iter, iter, comp, cont, BAD_alloc) static_assert(SFINAEs_away); // Cannot deduce from (iter, iter, comp, cont, DIFFERENT_alloc) static_assert(SFINAEs_away); // (comp, alloc) // // Cannot deduce from (ALLOC_as_comp, alloc) static_assert(SFINAEs_away); // Cannot deduce from (comp, BAD_alloc) static_assert(SFINAEs_away); // (comp, cont, alloc) // // Cannot deduce from (ALLOC_as_comp, cont, alloc) static_assert(SFINAEs_away); // Cannot deduce from (comp, ALLOC_as_cont, alloc) static_assert(SFINAEs_away); // Cannot deduce from (comp, cont, BAD_alloc) static_assert(SFINAEs_away); // Cannot deduce from (comp, cont, DIFFERENT_alloc) static_assert(SFINAEs_away); // (comp, cont) // // Cannot deduce from (ALLOC_as_comp, cont) static_assert(SFINAEs_away); // Cannot deduce from (comp, ALLOC_as_cont) static_assert(SFINAEs_away); #if TEST_STD_VER >= 23 using Range = RangeT; using BadRange = BadRangeT; // (from_range, range) // // Cannot deduce from (from_range, BAD_range) static_assert(SFINAEs_away); // (from_range, range, compare) // // Cannot deduce from (from_range, BAD_range, compare) static_assert(SFINAEs_away); // (from_range, range, compare, alloc) // // Cannot deduce from (from_range, BAD_range, compare, alloc) static_assert(SFINAEs_away); // Cannot deduce from (from_range, range, compare, BAD_alloc) static_assert(SFINAEs_away); // Cannot deduce from (from_range, range, compare, DIFFERENT_alloc) static_assert(SFINAEs_away); // (from_range, range, alloc) // // Cannot deduce from (from_range, BAD_range, alloc) static_assert(SFINAEs_away); // Cannot deduce from (from_range, range, BAD_alloc) static_assert(SFINAEs_away); // Cannot deduce from (from_range, range, DIFFERENT_alloc) static_assert(SFINAEs_away); #endif // TEST_STD_VER >= 23 } return 0; }