//===----------------------------------------------------------------------===// // // 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, c++17, c++20 // // class flat_multimap // template iterator insert(P&& x); // template iterator insert(const_iterator hint, P&& x); #include #include #include #include #include #include #include #include "MinSequenceContainer.h" #include "../helpers.h" #include "test_macros.h" #include "test_iterators.h" #include "min_allocator.h" // Constraints: is_constructible_v, P> is true. template concept CanInsert = requires(M m, Args&&... args) { m.insert(std::forward(args)...); }; using Map = std::flat_multimap; using Iter = Map::const_iterator; static_assert(CanInsert&&>); static_assert(CanInsert&&>); static_assert(CanInsert&&>); static_assert(CanInsert&&>); static_assert(!CanInsert); static_assert(!CanInsert); template constexpr void test() { using Key = typename KeyContainer::value_type; using Value = typename ValueContainer::value_type; using M = std::flat_multimap; { // insert(P&&) bool transparent_used = false; TransparentComparator c(transparent_used); M m(std::sorted_equivalent, {{1, 1}, {2, 2}, {2, 3}, {4, 4}}, c); assert(!transparent_used); std::same_as decltype(auto) res = m.insert(std::pair(ConvertibleTransparent{3}, 3)); assert(res->first == 3); assert(res->second == 3); // Unlike flat_set, here we can't use key_compare to compare value_type versus P, // so we must eagerly convert to value_type. assert(!transparent_used); } { // insert(const_iterator, P&&) bool transparent_used = false; TransparentComparator c(transparent_used); M m(std::sorted_equivalent, {{1, 1}, {2, 2}, {2, 3}, {4, 4}}, c); std::same_as decltype(auto) res = m.insert(m.begin(), std::pair(ConvertibleTransparent{3}, 3)); assert(res->first == 3); assert(res->second == 3); // Unlike flat_set, here we can't use key_compare to compare value_type versus P, // so we must eagerly convert to value_type. assert(!transparent_used); } } constexpr bool test() { test, std::vector>(); #ifndef __cpp_lib_constexpr_deque if (!TEST_IS_CONSTANT_EVALUATED) #endif test, std::vector>(); test, MinSequenceContainer>(); test>, std::vector>>(); { // no ambiguity between insert(pos, P&&) and insert(first, last) using M = std::flat_multimap; struct Evil { operator M::value_type() const; operator M::const_iterator() const; }; std::flat_multimap m; ASSERT_SAME_TYPE(decltype(m.insert(Evil())), M::iterator); ASSERT_SAME_TYPE(decltype(m.insert(m.begin(), Evil())), M::iterator); ASSERT_SAME_TYPE(decltype(m.insert(m.begin(), m.end())), void); } if (!TEST_IS_CONSTANT_EVALUATED) { { auto insert_func = [](auto& m, auto key_arg, auto value_arg) { using FlatMap = std::decay_t; using tuple_type = std::tuple; tuple_type t(key_arg, value_arg); m.insert(t); }; test_emplace_exception_guarantee(insert_func); } { auto insert_func_iter = [](auto& m, auto key_arg, auto value_arg) { using FlatMap = std::decay_t; using tuple_type = std::tuple; tuple_type t(key_arg, value_arg); m.insert(m.begin(), t); }; test_emplace_exception_guarantee(insert_func_iter); } } { // LWG4239 std::string and C string literal using M = std::flat_multimap>; M m{{"alpha", 1}, {"beta", 2}, {"beta", 1}, {"eta", 3}, {"gamma", 3}}; auto it = m.insert({"beta", 1}); assert(it == m.begin() + 3); auto it2 = m.insert(m.begin(), {"beta2", 2}); assert(it2 == m.begin() + 4); } return true; } int main(int, char**) { test(); #if TEST_STD_VER >= 26 static_assert(test()); #endif return 0; }