135 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 K> pair<iterator, bool> insert(P&& x);14// template<class K> iterator insert(const_iterator hint, P&& x);15 16#include <algorithm>17#include <compare>18#include <concepts>19#include <deque>20#include <flat_map>21#include <functional>22#include <tuple>23 24#include "MinSequenceContainer.h"25#include "../helpers.h"26#include "test_macros.h"27#include "test_iterators.h"28#include "min_allocator.h"29 30// Constraints: is_constructible_v<pair<key_type, mapped_type>, P> is true.31template <class M, class... Args>32concept CanInsert = requires(M m, Args&&... args) { m.insert(std::forward<Args>(args)...); };33 34using Map = std::flat_map<int, double>;35using Iter = Map::const_iterator;36 37static_assert(CanInsert<Map, std::pair<short, double>&&>);38static_assert(CanInsert<Map, Iter, std::pair<short, double>&&>);39static_assert(CanInsert<Map, std::tuple<short, double>&&>);40static_assert(CanInsert<Map, Iter, std::tuple<short, double>&&>);41static_assert(!CanInsert<Map, int>);42static_assert(!CanInsert<Map, Iter, int>);43 44constexpr bool test() {45 {46 // template<class K> pair<iterator, bool> insert(P&& x);47 bool transparent_used = false;48 TransparentComparator c(transparent_used);49 using M = std::flat_map<int, int, TransparentComparator>;50 M m(std::sorted_unique, {{1, 1}, {2, 2}, {4, 4}}, c);51 assert(!transparent_used);52 53 std::same_as<std::pair<typename M::iterator, bool>> decltype(auto) res =54 m.insert(std::pair(ConvertibleTransparent<int>{3}, 3));55 56 assert(res.second);57 assert(res.first->first == 3);58 assert(res.first->second == 3);59 // Unlike flat_set, here we can't use key_compare to compare value_type versus P,60 // so we must eagerly convert to value_type.61 assert(!transparent_used);62 }63 {64 // template<class K> iterator insert(const_iterator hint, P&& x);65 bool transparent_used = false;66 TransparentComparator c(transparent_used);67 using M = std::flat_map<int, int, TransparentComparator>;68 M m(std::sorted_unique, {{1, 1}, {2, 2}, {4, 4}}, c);69 assert(!transparent_used);70 71 std::same_as<typename M::iterator> decltype(auto) res =72 m.insert(m.begin(), std::pair(ConvertibleTransparent<int>{3}, 3));73 74 assert(res->first == 3);75 assert(res->second == 3);76 // Unlike flat_set, here we can't use key_compare to compare value_type versus P,77 // so we must eagerly convert to value_type.78 assert(!transparent_used);79 }80 {81 // no ambiguity between insert(pos, P&&) and insert(first, last)82 using M = std::flat_map<int, int>;83 struct Evil {84 operator M::value_type() const;85 operator M::const_iterator() const;86 };87 std::flat_map<int, int> m;88 ASSERT_SAME_TYPE(decltype(m.insert(Evil())), std::pair<M::iterator, bool>);89 ASSERT_SAME_TYPE(decltype(m.insert(m.begin(), Evil())), M::iterator);90 ASSERT_SAME_TYPE(decltype(m.insert(m.begin(), m.end())), void);91 }92 93 if (!TEST_IS_CONSTANT_EVALUATED) {94 {95 auto insert_func = [](auto& m, auto key_arg, auto value_arg) {96 using FlatMap = std::decay_t<decltype(m)>;97 using tuple_type = std::tuple<typename FlatMap::key_type, typename FlatMap::mapped_type>;98 tuple_type t(key_arg, value_arg);99 m.insert(t);100 };101 test_emplace_exception_guarantee(insert_func);102 }103 {104 auto insert_func_iter = [](auto& m, auto key_arg, auto value_arg) {105 using FlatMap = std::decay_t<decltype(m)>;106 using tuple_type = std::tuple<typename FlatMap::key_type, typename FlatMap::mapped_type>;107 tuple_type t(key_arg, value_arg);108 m.insert(m.begin(), t);109 };110 test_emplace_exception_guarantee(insert_func_iter);111 }112 }113 {114 // LWG4239 std::string and C string literal115 using M = std::flat_map<std::string, int, std::less<>>;116 M m{{"alpha", 1}, {"beta", 2}, {"epsilon", 1}, {"eta", 3}, {"gamma", 3}};117 auto [it, inserted] = m.insert({"alpha", 1});118 assert(!inserted);119 assert(it == m.begin());120 auto it2 = m.insert(m.begin(), {"beta2", 2});121 assert(it2 == m.begin() + 2);122 }123 124 return true;125}126 127int main(int, char**) {128 test();129#if TEST_STD_VER >= 26130 static_assert(test());131#endif132 133 return 0;134}135