178 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 11// <flat_set>12 13// explicit flat_multiset(container_type key_cont, const key_compare& comp = key_compare());14// template<class Allocator>15// flat_multiset(const container_type& key_cont, const Allocator& a);16// template<class Alloc>17// flat_multiset(const container_type& key_cont, const key_compare& comp, const Alloc& a);18 19#include <algorithm>20#include <deque>21#include <flat_set>22#include <functional>23#include <vector>24 25#include "min_allocator.h"26#include "MoveOnly.h"27#include "test_allocator.h"28#include "test_iterators.h"29#include "test_macros.h"30#include "../../../test_compare.h"31 32template <class T>33void conversion_test(T);34 35template <class T, class... Args>36concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };37 38template <template <class...> class KeyContainer>39constexpr void test() {40 {41 // The constructors in this subclause shall not participate in overload42 // resolution unless uses_allocator_v<container_type, Alloc> is true43 44 using C = test_less<int>;45 using A1 = test_allocator<int>;46 using A2 = other_allocator<int>;47 using V1 = KeyContainer<int, A1>;48 using V2 = KeyContainer<int, A2>;49 using M1 = std::flat_multiset<int, C, V1>;50 using M2 = std::flat_multiset<int, C, V2>;51 static_assert(std::is_constructible_v<M1, const V1&, const A1&>);52 static_assert(std::is_constructible_v<M2, const V2&, const A2&>);53 static_assert(!std::is_constructible_v<M1, const V1&, const A2&>);54 static_assert(!std::is_constructible_v<M2, const V2&, const A1&>);55 56 static_assert(std::is_constructible_v<M1, const V1&, const C&, const A1&>);57 static_assert(std::is_constructible_v<M2, const V2&, const C&, const A2&>);58 static_assert(!std::is_constructible_v<M1, const V1&, const C&, const A2&>);59 static_assert(!std::is_constructible_v<M2, const V2&, const C&, const A1&>);60 }61 {62 // flat_multiset(container_type)63 using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>;64 KeyContainer<int> ks = {1, 1, 1, 2, 2, 3, 2, 3, 3};65 auto m = M(ks);66 int expected[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};67 assert(std::ranges::equal(m, expected));68 69 // explicit(false)70 static_assert(std::is_constructible_v<M, const KeyContainer<int>&>);71 static_assert(!ImplicitlyConstructible<M, const KeyContainer<int>&>);72 73 m = M(std::move(ks));74 assert(ks.empty()); // it was moved-from75 assert(std::ranges::equal(m, expected));76 }77 {78 // flat_multiset(container_type)79 // move-only80 int expected[] = {3, 3, 2, 1};81 using Ks = KeyContainer<MoveOnly, min_allocator<MoveOnly>>;82 using M = std::flat_multiset<MoveOnly, std::greater<MoveOnly>, Ks>;83 Ks ks;84 ks.push_back(1);85 ks.push_back(3);86 ks.push_back(3);87 ks.push_back(2);88 auto m = M(std::move(ks));89 assert(ks.empty()); // it was moved-from90 assert(std::ranges::equal(m, expected, std::equal_to<>()));91 }92 {93 // flat_multiset(container_type)94 // container's allocators are used95 using A = test_allocator<int>;96 using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A>>;97 auto ks = KeyContainer<int, A>({1, 1, 1, 2, 2, 3, 2, 3, 3}, A(5));98 auto m = M(std::move(ks));99 assert(ks.empty()); // it was moved-from100 assert((m == M{1, 1, 1, 2, 2, 2, 3, 3, 3}));101 auto keys = std::move(m).extract();102 assert(keys.get_allocator() == A(5));103 }104 {105 // flat_multiset(container_type, key_compare)106 using C = test_less<int>;107 using M = std::flat_multiset<int, C, KeyContainer<int>>;108 KeyContainer<int> ks = {1, 1, 1, 2, 2, 3, 2, 3, 3};109 auto m = M(ks, C(4));110 assert(std::ranges::equal(m, std::vector<int>{1, 1, 1, 2, 2, 2, 3, 3, 3}));111 assert(m.key_comp() == C(4));112 113 // explicit114 static_assert(std::is_constructible_v<M, const KeyContainer<int>&, const C&>);115 static_assert(!ImplicitlyConstructible<M, const KeyContainer<int>&, const C&>);116 }117 {118 // flat_multiset(container_type , const Allocator&)119 using A = test_allocator<int>;120 using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A>>;121 auto ks = KeyContainer<int, A>({1, 1, 1, 2, 2, 3, 2, 3, 3}, A(5));122 auto m = M(ks, A(4)); // replaces the allocators123 assert(!ks.empty()); // it was an lvalue above124 assert((m == M{1, 1, 1, 2, 2, 2, 3, 3, 3}));125 auto keys = M(m).extract();126 assert(keys.get_allocator() == A(4));127 128 // explicit(false)129 static_assert(ImplicitlyConstructible<M, const KeyContainer<int, A>&, const A&>);130 M m2 = {ks, A(4)}; // implicit ctor131 assert(!ks.empty()); // it was an lvalue above132 assert(m2 == m);133 auto keys2 = std::move(m).extract();134 assert(keys2.get_allocator() == A(4));135 }136 {137 // flat_multiset(container_type , const Allocator&)138 using C = test_less<int>;139 using A = test_allocator<int>;140 using M = std::flat_multiset<int, C, KeyContainer<int, A>>;141 KeyContainer<int, A> ks = {1, 1, 1, 2, 2, 3, 2, 3, 3};142 auto m = M(ks, C(4), A(5));143 assert(std::ranges::equal(m, KeyContainer<int, A>{1, 1, 1, 2, 2, 2, 3, 3, 3}));144 assert(m.key_comp() == C(4));145 auto m_copy = m;146 auto keys = std::move(m_copy).extract();147 assert(keys.get_allocator() == A(5));148 149 // explicit(false)150 static_assert(ImplicitlyConstructible<M, const KeyContainer<int, A>&, const A&>);151 M m2 = {ks, C(4), A(5)};152 assert(m2 == m);153 assert(m2.key_comp() == C(4));154 keys = std::move(m2).extract();155 assert(keys.get_allocator() == A(5));156 }157}158 159constexpr bool test() {160 test<std::vector>();161 162#ifndef __cpp_lib_constexpr_deque163 if (!TEST_IS_CONSTANT_EVALUATED)164#endif165 test<std::deque>();166 167 return true;168}169 170int main(int, char**) {171 test();172#if TEST_STD_VER >= 26173 static_assert(test());174#endif175 176 return 0;177}178