Skip to content

Commit

Permalink
Update libcxx/unord.multimap
Browse files Browse the repository at this point in the history
  • Loading branch information
morzhovets committed Oct 18, 2024
1 parent 5738eb8 commit 06a1e4b
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 90 deletions.
8 changes: 8 additions & 0 deletions test/sources/libcxx/UnorderedMultiMapTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ LIBCXX_TEST_BEGIN(cnstr_dtor_noexcept)
#include "unord.multimap/unord.multimap.cnstr/dtor_noexcept.pass.cpp"
LIBCXX_TEST_END

LIBCXX_TEST_BEGIN(cnstr_from_range)
#include "unord.multimap/unord.multimap.cnstr/from_range.pass.cpp"
LIBCXX_TEST_END

LIBCXX_TEST_BEGIN(cnstr_init)
#include "unord.multimap/unord.multimap.cnstr/init.pass.cpp"
LIBCXX_TEST_END
Expand Down Expand Up @@ -345,6 +349,10 @@ LIBCXX_TEST_BEGIN(modifiers_insert_init)
#include "unord.multimap/unord.multimap.modifiers/insert_init.pass.cpp"
LIBCXX_TEST_END

LIBCXX_TEST_BEGIN(modifiers_insert_iter_iter)
#include "unord.multimap/unord.multimap.modifiers/insert_iter_iter.pass.cpp"
LIBCXX_TEST_END

LIBCXX_TEST_BEGIN(modifiers_insert_range)
#include "unord.multimap/unord.multimap.modifiers/insert_range.pass.cpp"
LIBCXX_TEST_END
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,28 @@
// unordered_multimap(initializer_list<pair<Key, T>>, typename see below::size_type, Hash,
// Allocator)
// -> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>;
//
// template<ranges::input_range R, class Hash = hash<range-key-type<R>>,
// class Pred = equal_to<range-key-type<R>>,
// class Allocator = allocator<range-to-alloc-type<R>>>
// unordered_multimap(from_range_t, R&&, typename see below::size_type = see below,
// Hash = Hash(), Pred = Pred(), Allocator = Allocator())
// -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, Hash, Pred, Allocator>; // C++23
//
// template<ranges::input_range R, class Allocator>
// unordered_multimap(from_range_t, R&&, typename see below::size_type, Allocator)
// -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>,
// equal_to<range-key-type<R>>, Allocator>; // C++23
//
// template<ranges::input_range R, class Allocator>
// unordered_multimap(from_range_t, R&&, Allocator)
// -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>,
// equal_to<range-key-type<R>>, Allocator>; // C++23
//
// template<ranges::input_range R, class Hash, class Allocator>
// unordered_multimap(from_range_t, R&&, typename see below::size_type, Hash, Allocator)
// -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, Hash,
// equal_to<range-key-type<R>>, Allocator>; // C++23

using P = std::pair<int, long>;
using PC = std::pair<const int, long>;
Expand Down Expand Up @@ -218,6 +240,58 @@ int main(int, char**)
ASSERT_SAME_TYPE(decltype(m2), momo::stdish::unordered_multimap<int, int>);
}

#if TEST_STD_VER >= 23
{
using Range = std::array<P, 0>;
using Pred = test_equal_to<int>;
using DefaultPred = std::equal_to<int>;
using Hash = test_hash<int>;
using DefaultHash = momo::HashCoder<int>;
using Alloc = test_allocator<PC>;

{ // (from_range, range)
momo::stdish::unordered_multimap c(std::from_range, Range());
static_assert(std::is_same_v<decltype(c), momo::stdish::unordered_multimap<int, long>>);
}

{ // (from_range, range, n)
momo::stdish::unordered_multimap c(std::from_range, Range(), std::size_t());
static_assert(std::is_same_v<decltype(c), momo::stdish::unordered_multimap<int, long>>);
}

{ // (from_range, range, n, hash)
momo::stdish::unordered_multimap c(std::from_range, Range(), std::size_t(), Hash());
static_assert(std::is_same_v<decltype(c), momo::stdish::unordered_multimap<int, long, Hash>>);
}

{ // (from_range, range, n, hash, pred)
momo::stdish::unordered_multimap c(std::from_range, Range(), std::size_t(), Hash(), Pred());
static_assert(std::is_same_v<decltype(c), momo::stdish::unordered_multimap<int, long, Hash, Pred>>);
}

{ // (from_range, range, n, hash, pred, alloc)
momo::stdish::unordered_multimap c(std::from_range, Range(), std::size_t(), Hash(), Pred(), Alloc());
static_assert(std::is_same_v<decltype(c), momo::stdish::unordered_multimap<int, long, Hash, Pred, Alloc>>);
}

{ // (from_range, range, n, alloc)
momo::stdish::unordered_multimap c(std::from_range, Range(), std::size_t(), Alloc());
static_assert(std::is_same_v<decltype(c), momo::stdish::unordered_multimap<int, long, DefaultHash, DefaultPred, Alloc>>);
}

// TODO(LWG 2713): uncomment this test once the constructor is added.
{ // (from_range, range, alloc)
//momo::stdish::unordered_multimap c(std::from_range, Range(), Alloc());
//static_assert(std::is_same_v<decltype(c), momo::stdish::unordered_multimap<int, long, DefaultHash, DefaultPred, Alloc>>);
}

{ // (from_range, range, n, hash, alloc)
momo::stdish::unordered_multimap c(std::from_range, Range(), std::size_t(), Hash(), Alloc());
static_assert(std::is_same_v<decltype(c), momo::stdish::unordered_multimap<int, long, Hash, DefaultPred, Alloc>>);
}
}
#endif

#if MOMO_VERSION_MAJOR > 3
#if !(defined(TEST_MSVC) && _MSC_VER < 1930) && !(defined(TEST_GCC) && __GNUC__ < 11)
UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_multimap, std::unordered_multimap<int, long>>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Modified for https://github.com/morzhovets/momo project.
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20

// template<container-compatible-range<value_type> R>
// unordered_multimap(from_range_t, R&& rg, size_type n = see below,
// const hasher& hf = hasher(), const key_equal& eql = key_equal(),
// const allocator_type& a = allocator_type()); // C++23
//
// template<container-compatible-range<value_type> R>
// unordered_multimap(from_range_t, R&& rg, size_type n, const allocator_type& a)
// : unordered_multimap(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } // C++23
//
// template<container-compatible-range<value_type> R>
// unordered_multimap(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a)
// : unordered_multimap(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { } // C++23

void test_duplicates() {
using T = std::pair<const int, char>;
std::array input = {
T{1, 'a'}, T{2, 'a'}, T{3, 'a'}, T{3, 'b'}, T{3, 'c'}, T{2, 'b'}, T{4, 'a'}
};
auto c = std::unordered_multimap<int, char>(std::from_range, input);
assert(std::ranges::is_permutation(input, c));
}

int main(int, char**) {
using T = std::pair<const int, int>;
for_all_iterators_and_allocators<T>([]<class Iter, class Sent, class Alloc>() {
test_unordered_map<std::unordered_multimap, int, int, Iter, Sent, test_hash<int>, test_equal_to<int>, Alloc>();
});
test_unordered_map_move_only<std::unordered_multimap>();
test_duplicates();

static_assert(test_map_constraints<std::unordered_multimap, int, int, double, double>());

test_map_exception_safety_throwing_copy<std::unordered_multimap>();
test_map_exception_safety_throwing_allocator<std::unordered_multimap, int, int>();

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Modified for https://github.com/morzhovets/momo project.
//
//===----------------------------------------------------------------------===//

// <unordered_map>

// template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>,
// class Alloc = allocator<pair<const Key, T>>>
// class unordered_multimap

// template <class InputIterator>
// void insert(InputIterator first, InputIterator last);

int main(int, char**)
{
{
typedef std::unordered_multimap<int, std::string> C;
typedef std::pair<int, std::string> P;
P a[] =
{
P(1, "one"),
P(2, "two"),
P(3, "three"),
P(4, "four"),
P(1, "four"),
P(2, "four"),
};
C c;
c.insert(cpp17_input_iterator<P*>(a), cpp17_input_iterator<P*>(a + sizeof(a)/sizeof(a[0])));
assert(c.size() == 6);
typedef std::pair<C::iterator, C::iterator> Eq;
Eq eq = c.equal_range(1);
assert(std::distance(eq.first, eq.second) == 2);
std::multiset<std::string> s;
s.insert("one");
s.insert("four");
CheckConsecutiveKeys<C::const_iterator>(c.find(1), c.end(), 1, s);
eq = c.equal_range(2);
assert(std::distance(eq.first, eq.second) == 2);
s.insert("two");
s.insert("four");
CheckConsecutiveKeys<C::const_iterator>(c.find(2), c.end(), 2, s);
eq = c.equal_range(3);
assert(std::distance(eq.first, eq.second) == 1);
C::iterator k = eq.first;
assert(k->first == 3);
assert(k->second == "three");
eq = c.equal_range(4);
assert(std::distance(eq.first, eq.second) == 1);
k = eq.first;
assert(k->first == 4);
assert(k->second == "four");
assert(static_cast<std::size_t>(std::distance(c.begin(), c.end())) == c.size());
assert(static_cast<std::size_t>(std::distance(c.cbegin(), c.cend())) == c.size());
}
#if TEST_STD_VER >= 11
{
typedef std::unordered_multimap<int, std::string, std::hash<int>, std::equal_to<int>,
min_allocator<std::pair<const int, std::string>>> C;
typedef std::pair<int, std::string> P;
P a[] =
{
P(1, "one"),
P(2, "two"),
P(3, "three"),
P(4, "four"),
P(1, "four"),
P(2, "four"),
};
C c;
c.insert(cpp17_input_iterator<P*>(a), cpp17_input_iterator<P*>(a + sizeof(a)/sizeof(a[0])));
assert(c.size() == 6);
typedef std::pair<C::iterator, C::iterator> Eq;
Eq eq = c.equal_range(1);
assert(std::distance(eq.first, eq.second) == 2);
std::multiset<std::string> s;
s.insert("one");
s.insert("four");
CheckConsecutiveKeys<C::const_iterator>(c.find(1), c.end(), 1, s);
eq = c.equal_range(2);
assert(std::distance(eq.first, eq.second) == 2);
s.insert("two");
s.insert("four");
CheckConsecutiveKeys<C::const_iterator>(c.find(2), c.end(), 2, s);
eq = c.equal_range(3);
assert(std::distance(eq.first, eq.second) == 1);
C::iterator k = eq.first;
assert(k->first == 3);
assert(k->second == "three");
eq = c.equal_range(4);
assert(std::distance(eq.first, eq.second) == 1);
k = eq.first;
assert(k->first == 4);
assert(k->second == "four");
assert(static_cast<std::size_t>(std::distance(c.begin(), c.end())) == c.size());
assert(static_cast<std::size_t>(std::distance(c.cbegin(), c.cend())) == c.size());
}
#endif

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,100 +10,31 @@
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
// Some fields in the test case variables are deliberately not explicitly initialized, this silences a warning on GCC.
// ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-missing-field-initializers

// <unordered_map>

// template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>,
// class Alloc = allocator<pair<const Key, T>>>
// class unordered_multimap
// template<container-compatible-range<value_type> R>
// void insert_range(R&& rg); // C++23

int main(int, char**) {
// Note: we want to use a pair with non-const elements for input (an assignable type is a lot more convenient) but
// have to use the exact `value_type` of the map (that is, `pair<const K, V>`) for the allocator.
using Pair = std::pair<int, char>;
using ConstPair = std::pair<const int, char>;
for_all_iterators_and_allocators<ConstPair, const Pair*>([]<class Iter, class Sent, class Alloc>() {
test_map_set_insert_range<std::unordered_multimap<int, char, test_hash<int>, test_equal_to<int>, Alloc>, Pair, Iter, Sent>(/*allow_duplicates=*/true);
});

// template <class InputIterator>
// void insert(InputIterator first, InputIterator last);
static_assert(test_map_constraints_insert_range<std::unordered_multimap, int, int, char, double>());

int main(int, char**)
{
{
typedef std::unordered_multimap<int, std::string> C;
typedef std::pair<int, std::string> P;
P a[] =
{
P(1, "one"),
P(2, "two"),
P(3, "three"),
P(4, "four"),
P(1, "four"),
P(2, "four"),
};
C c;
c.insert(cpp17_input_iterator<P*>(a), cpp17_input_iterator<P*>(a + sizeof(a)/sizeof(a[0])));
assert(c.size() == 6);
typedef std::pair<C::iterator, C::iterator> Eq;
Eq eq = c.equal_range(1);
assert(std::distance(eq.first, eq.second) == 2);
std::multiset<std::string> s;
s.insert("one");
s.insert("four");
CheckConsecutiveKeys<C::const_iterator>(c.find(1), c.end(), 1, s);
eq = c.equal_range(2);
assert(std::distance(eq.first, eq.second) == 2);
s.insert("two");
s.insert("four");
CheckConsecutiveKeys<C::const_iterator>(c.find(2), c.end(), 2, s);
eq = c.equal_range(3);
assert(std::distance(eq.first, eq.second) == 1);
C::iterator k = eq.first;
assert(k->first == 3);
assert(k->second == "three");
eq = c.equal_range(4);
assert(std::distance(eq.first, eq.second) == 1);
k = eq.first;
assert(k->first == 4);
assert(k->second == "four");
assert(static_cast<std::size_t>(std::distance(c.begin(), c.end())) == c.size());
assert(static_cast<std::size_t>(std::distance(c.cbegin(), c.cend())) == c.size());
}
#if TEST_STD_VER >= 11
{
typedef std::unordered_multimap<int, std::string, std::hash<int>, std::equal_to<int>,
min_allocator<std::pair<const int, std::string>>> C;
typedef std::pair<int, std::string> P;
P a[] =
{
P(1, "one"),
P(2, "two"),
P(3, "three"),
P(4, "four"),
P(1, "four"),
P(2, "four"),
};
C c;
c.insert(cpp17_input_iterator<P*>(a), cpp17_input_iterator<P*>(a + sizeof(a)/sizeof(a[0])));
assert(c.size() == 6);
typedef std::pair<C::iterator, C::iterator> Eq;
Eq eq = c.equal_range(1);
assert(std::distance(eq.first, eq.second) == 2);
std::multiset<std::string> s;
s.insert("one");
s.insert("four");
CheckConsecutiveKeys<C::const_iterator>(c.find(1), c.end(), 1, s);
eq = c.equal_range(2);
assert(std::distance(eq.first, eq.second) == 2);
s.insert("two");
s.insert("four");
CheckConsecutiveKeys<C::const_iterator>(c.find(2), c.end(), 2, s);
eq = c.equal_range(3);
assert(std::distance(eq.first, eq.second) == 1);
C::iterator k = eq.first;
assert(k->first == 3);
assert(k->second == "three");
eq = c.equal_range(4);
assert(std::distance(eq.first, eq.second) == 1);
k = eq.first;
assert(k->first == 4);
assert(k->second == "four");
assert(static_cast<std::size_t>(std::distance(c.begin(), c.end())) == c.size());
assert(static_cast<std::size_t>(std::distance(c.cbegin(), c.cend())) == c.size());
}
#endif
test_map_insert_range_move_only<std::unordered_multimap>();

test_map_insert_range_exception_safety_throwing_copy<std::unordered_multimap>();
test_unord_map_insert_range_exception_safety_throwing_allocator<std::unordered_multimap, int, int>();

return 0;
}

0 comments on commit 06a1e4b

Please sign in to comment.