236 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_map>12 13// template <class InputIterator>14// flat_map(InputIterator first, InputIterator last, const key_compare& comp = key_compare());15// template<class InputIterator, class Allocator>16// flat_map(InputIterator first, InputIterator last, const Allocator& a);17// template<class InputIterator, class Allocator>18// flat_map(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a);19 20#include <algorithm>21#include <deque>22#include <flat_map>23#include <functional>24#include <vector>25#include <ranges>26 27#include "MinSequenceContainer.h"28#include "min_allocator.h"29#include "test_allocator.h"30#include "test_iterators.h"31#include "test_macros.h"32#include "../helpers.h"33#include "../../../test_compare.h"34 35template <class KeyContainer, class ValueContainer>36constexpr void test() {37 using Key = typename KeyContainer::value_type;38 using Value = typename ValueContainer::value_type;39 using P = std::pair<Key, Value>;40 P ar[] = {{1, 1}, {1, 2}, {1, 3}, {2, 4}, {2, 5}, {3, 6}, {2, 7}, {3, 8}, {3, 9}};41 {42 // flat_map(InputIterator , InputIterator)43 // cpp17_input_iterator44 using M = std::flat_map<Key, Value, std::less<Key>, KeyContainer, ValueContainer>;45 auto m = M(cpp17_input_iterator<const P*>(ar), cpp17_input_iterator<const P*>(ar + 9));46 assert(std::ranges::equal(m.keys(), KeyContainer{1, 2, 3}));47 check_possible_values(48 m.values(),49 std::vector<std::vector<Value>>{50 {1, 2, 3},51 {4, 5, 7},52 {6, 8, 9},53 });54 55 // explicit(false)56 M m2 = {cpp17_input_iterator<const P*>(ar), cpp17_input_iterator<const P*>(ar + 9)};57 assert(m2 == m);58 }59 {60 // flat_map(InputIterator , InputIterator)61 // greater62 using M = std::flat_map<Key, Value, std::greater<Key>, KeyContainer, ValueContainer>;63 auto m = M(cpp17_input_iterator<const P*>(ar), cpp17_input_iterator<const P*>(ar + 9));64 assert(std::ranges::equal(m.keys(), KeyContainer{3, 2, 1}));65 check_possible_values(66 m.values(),67 std::vector<std::vector<Value>>{68 {6, 8, 9},69 {4, 5, 7},70 {1, 2, 3},71 });72 }73 {74 // flat_map(InputIterator , InputIterator)75 // Test when the operands are of array type (also contiguous iterator type)76 using M = std::flat_map<Key, Value, std::greater<Key>, KeyContainer, ValueContainer>;77 auto m = M(ar, ar);78 assert(m.empty());79 }80 {81 // flat_map(InputIterator , InputIterator, const key_compare&)82 using C = test_less<Key>;83 using M = std::flat_map<Key, Value, C, KeyContainer, ValueContainer>;84 auto m = M(ar, ar + 9, C(3));85 assert(std::ranges::equal(m.keys(), KeyContainer{1, 2, 3}));86 check_possible_values(87 m.values(),88 std::vector<std::vector<Value>>{89 {1, 2, 3},90 {4, 5, 7},91 {6, 8, 9},92 });93 assert(m.key_comp() == C(3));94 95 // explicit(false)96 M m2 = {ar, ar + 9, C(3)};97 assert(m2 == m);98 assert(m2.key_comp() == C(3));99 }100}101 102template <template <class...> class KeyContainer, template <class...> class ValueContainer>103constexpr void test_alloc() {104 using P = std::pair<int, short>;105 P ar[] = {{1, 1}, {1, 2}, {1, 3}, {2, 4}, {2, 5}, {3, 6}, {2, 7}, {3, 8}, {3, 9}};106 107 {108 // flat_map(InputIterator , InputIterator, const Allocator&)109 using A1 = test_allocator<int>;110 using A2 = test_allocator<short>;111 using M = std::flat_map<int, short, std::less<int>, KeyContainer<int, A1>, ValueContainer<short, A2>>;112 auto m = M(ar, ar + 9, A1(5));113 assert(std::ranges::equal(m.keys(), KeyContainer<int, A1>{1, 2, 3}));114 check_possible_values(115 m.values(),116 std::vector<std::vector<short>>{117 {1, 2, 3},118 {4, 5, 7},119 {6, 8, 9},120 });121 assert(m.keys().get_allocator() == A1(5));122 assert(m.values().get_allocator() == A2(5));123 }124 {125 // flat_map(InputIterator , InputIterator, const Allocator&)126 // explicit(false)127 using A1 = test_allocator<int>;128 using A2 = test_allocator<short>;129 using M = std::flat_map<int, short, std::less<int>, KeyContainer<int, A1>, ValueContainer<short, A2>>;130 M m = {ar, ar + 9, A1(5)}; // implicit ctor131 assert(std::ranges::equal(m.keys(), KeyContainer<int, A1>{1, 2, 3}));132 check_possible_values(133 m.values(),134 std::vector<std::vector<short>>{135 {1, 2, 3},136 {4, 5, 7},137 {6, 8, 9},138 });139 assert(m.keys().get_allocator() == A1(5));140 assert(m.values().get_allocator() == A2(5));141 }142 {143 // flat_map(InputIterator , InputIterator, const key_compare&, const Allocator&)144 using C = test_less<int>;145 using A1 = test_allocator<int>;146 using A2 = test_allocator<short>;147 using M = std::flat_map<int, short, C, KeyContainer<int, A1>, ValueContainer<short, A2>>;148 auto m = M(ar, ar + 9, C(3), A1(5));149 assert(std::ranges::equal(m.keys(), KeyContainer<int, A1>{1, 2, 3}));150 check_possible_values(151 m.values(),152 std::vector<std::vector<short>>{153 {1, 2, 3},154 {4, 5, 7},155 {6, 8, 9},156 });157 assert(m.key_comp() == C(3));158 assert(m.keys().get_allocator() == A1(5));159 assert(m.values().get_allocator() == A2(5));160 }161 {162 // flat_map(InputIterator , InputIterator, const key_compare&, const Allocator&)163 // explicit(false)164 using A1 = test_allocator<int>;165 using A2 = test_allocator<short>;166 using M = std::flat_map<int, short, std::less<int>, KeyContainer<int, A1>, ValueContainer<short, A2>>;167 M m = {ar, ar + 9, {}, A2(5)}; // implicit ctor168 assert(std::ranges::equal(m.keys(), KeyContainer<int, A1>{1, 2, 3}));169 check_possible_values(170 m.values(),171 std::vector<std::vector<short>>{172 {1, 2, 3},173 {4, 5, 7},174 {6, 8, 9},175 });176 assert(m.keys().get_allocator() == A1(5));177 assert(m.values().get_allocator() == A2(5));178 }179}180 181constexpr bool test() {182 {183 // The constructors in this subclause shall not participate in overload184 // resolution unless uses_allocator_v<key_container_type, Alloc> is true185 // and uses_allocator_v<mapped_container_type, Alloc> is true.186 187 using C = test_less<int>;188 using A1 = test_allocator<int>;189 using A2 = other_allocator<int>;190 using V1 = std::vector<int, A1>;191 using V2 = std::vector<int, A2>;192 using M1 = std::flat_map<int, int, C, V1, V1>;193 using M2 = std::flat_map<int, int, C, V1, V2>;194 using M3 = std::flat_map<int, int, C, V2, V1>;195 using Iter1 = typename M1::iterator;196 using Iter2 = typename M2::iterator;197 using Iter3 = typename M3::iterator;198 static_assert(std::is_constructible_v<M1, Iter1, Iter1, const A1&>);199 static_assert(!std::is_constructible_v<M1, Iter1, Iter1, const A2&>);200 static_assert(!std::is_constructible_v<M2, Iter2, Iter2, const A2&>);201 static_assert(!std::is_constructible_v<M3, Iter3, Iter3, const A2&>);202 203 static_assert(std::is_constructible_v<M1, Iter1, Iter1, const C&, const A1&>);204 static_assert(!std::is_constructible_v<M1, Iter1, Iter1, const C&, const A2&>);205 static_assert(!std::is_constructible_v<M2, Iter2, Iter2, const C&, const A2&>);206 static_assert(!std::is_constructible_v<M3, Iter3, Iter3, const C&, const A2&>);207 }208 209 test<std::vector<int>, std::vector<int>>();210 test<std::vector<int>, std::vector<double>>();211 test<MinSequenceContainer<int>, MinSequenceContainer<double>>();212 test<std::vector<int, min_allocator<int>>, std::vector<double, min_allocator<double>>>();213 test<std::vector<int, min_allocator<int>>, std::vector<int, min_allocator<int>>>();214 215 test_alloc<std::vector, std::vector>();216 217#ifndef __cpp_lib_constexpr_deque218 if (!TEST_IS_CONSTANT_EVALUATED)219#endif220 {221 test<std::deque<int>, std::vector<double>>();222 test_alloc<std::deque, std::deque>();223 }224 225 return true;226}227 228int main(int, char**) {229 test();230#if TEST_STD_VER >= 26231 static_assert(test());232#endif233 234 return 0;235}236