mirror of
https://github.com/intel/llvm.git
synced 2026-01-21 20:53:29 +08:00
[libc++] Replace stable_sort with sort in flat_map (#121431)
Fixes #120788
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
#include <__algorithm/ranges_inplace_merge.h>
|
||||
#include <__algorithm/ranges_lower_bound.h>
|
||||
#include <__algorithm/ranges_partition_point.h>
|
||||
#include <__algorithm/ranges_stable_sort.h>
|
||||
#include <__algorithm/ranges_sort.h>
|
||||
#include <__algorithm/ranges_unique.h>
|
||||
#include <__algorithm/ranges_upper_bound.h>
|
||||
#include <__algorithm/remove_if.h>
|
||||
@@ -853,9 +853,7 @@ private:
|
||||
// is no invariant state to preserve
|
||||
_LIBCPP_HIDE_FROM_ABI void __sort_and_unique() {
|
||||
auto __zv = ranges::views::zip(__containers_.keys, __containers_.values);
|
||||
// To be consistent with std::map's behaviour, we use stable_sort instead of sort.
|
||||
// As a result, if there are duplicated keys, the first value in the original order will be taken.
|
||||
ranges::stable_sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); });
|
||||
ranges::sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); });
|
||||
auto __dup_start = ranges::unique(__zv, __key_equiv(__compare_)).begin();
|
||||
auto __dist = ranges::distance(__zv.begin(), __dup_start);
|
||||
__containers_.keys.erase(__containers_.keys.begin() + __dist, __containers_.keys.end());
|
||||
@@ -886,7 +884,7 @@ private:
|
||||
return __compare_(std::get<0>(__p1), std::get<0>(__p2));
|
||||
};
|
||||
if constexpr (!_WasSorted) {
|
||||
ranges::stable_sort(__zv.begin() + __append_start_offset, __end, __compare_key);
|
||||
ranges::sort(__zv.begin() + __append_start_offset, __end, __compare_key);
|
||||
} else {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
|
||||
__is_sorted_and_unique(__containers_.keys | ranges::views::drop(__append_start_offset)),
|
||||
|
||||
@@ -760,6 +760,8 @@ module std [system] {
|
||||
module ranges_sort {
|
||||
header "__algorithm/ranges_sort.h"
|
||||
export std.functional.ranges_operations
|
||||
export std.algorithm.sort
|
||||
export std.algorithm.make_projected
|
||||
}
|
||||
module ranges_stable_partition {
|
||||
header "__algorithm/ranges_stable_partition.h"
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <flat_map>
|
||||
|
||||
// flat_map(key_container_type key_cont, mapped_container_type mapped_cont);
|
||||
//
|
||||
// libc++ uses stable_sort to ensure that flat_map's behavior matches map's,
|
||||
// in terms of which duplicate items are kept.
|
||||
// This tests a conforming extension.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <flat_map>
|
||||
#include <random>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct Mod256 {
|
||||
bool operator()(int x, int y) const { return (x % 256) < (y % 256); }
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
std::mt19937 randomness;
|
||||
std::vector<uint16_t> values;
|
||||
std::vector<std::pair<uint16_t, uint16_t>> pairs;
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
uint16_t r = randomness();
|
||||
values.push_back(r);
|
||||
pairs.emplace_back(r, r);
|
||||
}
|
||||
|
||||
{
|
||||
std::map<uint16_t, uint16_t, Mod256> m(pairs.begin(), pairs.end());
|
||||
std::flat_map<uint16_t, uint16_t, Mod256> fm(values, values);
|
||||
assert(fm.size() == m.size());
|
||||
LIBCPP_ASSERT(std::ranges::equal(fm, m));
|
||||
}
|
||||
{
|
||||
std::map<uint16_t, uint16_t, Mod256> m(pairs.begin(), pairs.end());
|
||||
std::flat_map<uint16_t, uint16_t, Mod256> fm(values, values, Mod256());
|
||||
assert(fm.size() == m.size());
|
||||
LIBCPP_ASSERT(std::ranges::equal(fm, m));
|
||||
}
|
||||
{
|
||||
std::map<uint16_t, uint16_t, Mod256> m(pairs.begin(), pairs.end());
|
||||
std::flat_map<uint16_t, uint16_t, Mod256> fm(values, values, std::allocator<int>());
|
||||
assert(fm.size() == m.size());
|
||||
LIBCPP_ASSERT(std::ranges::equal(fm, m));
|
||||
}
|
||||
{
|
||||
std::map<uint16_t, uint16_t, Mod256> m(pairs.begin(), pairs.end());
|
||||
std::flat_map<uint16_t, uint16_t, Mod256> fm(values, values, Mod256(), std::allocator<int>());
|
||||
assert(fm.size() == m.size());
|
||||
LIBCPP_ASSERT(std::ranges::equal(fm, m));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <flat_map>
|
||||
|
||||
// template<class InputIterator>
|
||||
// flat_map(InputIterator first, InputIterator last, const key_compare& comp = key_compare())
|
||||
//
|
||||
// libc++ uses stable_sort to ensure that flat_map's behavior matches map's,
|
||||
// in terms of which duplicate items are kept.
|
||||
// This tests a conforming extension.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <flat_map>
|
||||
#include <random>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct Mod256 {
|
||||
bool operator()(int x, int y) const { return (x % 256) < (y % 256); }
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
std::mt19937 randomness;
|
||||
std::pair<uint16_t, uint16_t> pairs[200];
|
||||
for (auto& pair : pairs) {
|
||||
pair = {uint16_t(randomness()), uint16_t(randomness())};
|
||||
}
|
||||
|
||||
{
|
||||
std::map<uint16_t, uint16_t, Mod256> m(pairs, pairs + 200);
|
||||
std::flat_map<uint16_t, uint16_t, Mod256> fm(pairs, pairs + 200);
|
||||
assert(fm.size() == m.size());
|
||||
LIBCPP_ASSERT(std::ranges::equal(fm, m));
|
||||
}
|
||||
{
|
||||
std::map<uint16_t, uint16_t, Mod256> m(pairs, pairs + 200, std::allocator<int>());
|
||||
std::flat_map<uint16_t, uint16_t, Mod256> fm(pairs, pairs + 200, std::allocator<int>());
|
||||
assert(fm.size() == m.size());
|
||||
LIBCPP_ASSERT(std::ranges::equal(fm, m));
|
||||
}
|
||||
{
|
||||
std::map<uint16_t, uint16_t, Mod256> m(pairs, pairs + 200, Mod256());
|
||||
std::flat_map<uint16_t, uint16_t, Mod256> fm(pairs, pairs + 200, Mod256());
|
||||
assert(fm.size() == m.size());
|
||||
LIBCPP_ASSERT(std::ranges::equal(fm, m));
|
||||
}
|
||||
{
|
||||
std::map<uint16_t, uint16_t, Mod256> m(pairs, pairs + 200, Mod256(), std::allocator<int>());
|
||||
std::flat_map<uint16_t, uint16_t, Mod256> fm(pairs, pairs + 200, Mod256(), std::allocator<int>());
|
||||
assert(fm.size() == m.size());
|
||||
LIBCPP_ASSERT(std::ranges::equal(fm, m));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <flat_map>
|
||||
|
||||
// template<container-compatible-range<value_type> R>
|
||||
// void insert_range(R&& rg);
|
||||
//
|
||||
// libc++ uses stable_sort to ensure that flat_map's behavior matches map's,
|
||||
// in terms of which duplicate items are kept.
|
||||
// This tests a conforming extension.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <flat_map>
|
||||
#include <random>
|
||||
#include <ranges>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct Mod256 {
|
||||
bool operator()(int x, int y) const { return (x % 256) < (y % 256); }
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
{
|
||||
std::mt19937 randomness;
|
||||
std::pair<uint16_t, uint16_t> pairs[400];
|
||||
for (int i = 0; i < 400; ++i) {
|
||||
uint16_t r = randomness();
|
||||
pairs[i] = {r, r};
|
||||
}
|
||||
|
||||
std::map<uint16_t, uint16_t, Mod256> m(pairs, pairs + 200);
|
||||
std::flat_map<uint16_t, uint16_t, Mod256> fm(std::sorted_unique, m.begin(), m.end());
|
||||
assert(std::ranges::equal(fm, m));
|
||||
|
||||
fm.insert_range(std::views::counted(pairs + 200, 200));
|
||||
m.insert(pairs + 200, pairs + 400);
|
||||
assert(fm.size() == m.size());
|
||||
LIBCPP_ASSERT(std::ranges::equal(fm, m));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<std::pair<int, int>> v{{1, 2}, {1, 3}};
|
||||
std::flat_map<int, int> m;
|
||||
m.insert_range(v);
|
||||
assert(m.size() == 1);
|
||||
LIBCPP_ASSERT(m[1] == 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user