Skip to content
Merged
1 change: 1 addition & 0 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ add_benchmark(filesystem src/filesystem.cpp)
add_benchmark(fill src/fill.cpp)
add_benchmark(find_and_count src/find_and_count.cpp)
add_benchmark(find_first_of src/find_first_of.cpp)
add_benchmark(flat_meow_assign src/flat_meow_assign.cpp)
add_benchmark(has_single_bit src/has_single_bit.cpp)
add_benchmark(includes src/includes.cpp)
add_benchmark(integer_to_string src/integer_to_string.cpp)
Expand Down
52 changes: 52 additions & 0 deletions benchmarks/src/flat_meow_assign.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <benchmark/benchmark.h>
#include <flat_map>
#include <flat_set>
#include <string>

using namespace std;

void flat_map_strings(benchmark::State& state) {
flat_map<string, int> pieces;
Comment thread
StephanTLavavej marked this conversation as resolved.
for (auto _ : state) {
pieces = {{"soldier"s, 1}, {"soldier"s, 2}, {"soldier"s, 3}, {"soldier"s, 4}, {"soldier"s, 5}, {"soldier"s, 6},
{"soldier"s, 7}, {"soldier"s, 8}, {"tower"s, 9}, {"horse"s, 10}, {"elephant"s, 11}, {"vizier"s, 12},
{"king"s, 13}, {"elephant"s, 14}, {"horse"s, 15}, {"tower"s, 16}};
benchmark::DoNotOptimize(pieces);
}
}

void flat_set_strings(benchmark::State& state) {
flat_set<string> pieces;
for (auto _ : state) {
pieces = {"soldier"s, "soldier"s, "soldier"s, "soldier"s, "soldier"s, "soldier"s, "soldier"s, "soldier"s,
"tower"s, "horse"s, "elephant"s, "vizier"s, "king"s, "elephant"s, "horse"s, "tower"s};
benchmark::DoNotOptimize(pieces);
}
}

void flat_map_integers(benchmark::State& state) {
flat_map<int, int> pieces;
for (auto _ : state) {
pieces = {{'s', 1}, {'s', 2}, {'s', 3}, {'s', 4}, {'s', 5}, {'s', 6}, {'s', 7}, {'s', 8}, {'T', 9}, {'H', 10},
{'E', 11}, {'V', 12}, {'K', 13}, {'E', 14}, {'H', 15}, {'T', 16}};
benchmark::DoNotOptimize(pieces);
}
}

void flat_set_integers(benchmark::State& state) {
flat_set<int> pieces;
for (auto _ : state) {
pieces = {'s', 's', 's', 's', 's', 's', 's', 's', 'T', 'H', 'E', 'V', 'K', 'E', 'H', 'T'};
benchmark::DoNotOptimize(pieces);
}
}

BENCHMARK(flat_map_strings);
BENCHMARK(flat_set_strings);
BENCHMARK(flat_map_integers);
BENCHMARK(flat_set_integers);

BENCHMARK_MAIN();
6 changes: 6 additions & 0 deletions stl/inc/__msvc_string_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2148,6 +2148,12 @@ inline namespace literals {
} // namespace string_view_literals
} // namespace literals
#endif // _HAS_CXX17

#if _HAS_CXX23
template <class _Elem, class _Traits>
constexpr bool _Equivalence_is_equality_impl<basic_string_view<_Elem, _Traits>> =
_Is_implementation_handled_char_traits<_Traits>;
#endif // _HAS_CXX23
_STD_END

#pragma pop_macro("new")
Expand Down
15 changes: 12 additions & 3 deletions stl/inc/flat_map
Original file line number Diff line number Diff line change
Expand Up @@ -1084,12 +1084,21 @@ private:
_STL_INTERNAL_CHECK(_Is_sorted_and_unique());
}

auto _Erase_dupes_if_not_multi_pred() {
_STL_INTERNAL_STATIC_ASSERT(_IsUnique);
if constexpr (_Equivalence_is_equality<_Compare, _Key>) {
return [](const_reference _Left, const_reference _Right)
_STATIC_CALL_OPERATOR { return _Left.first == _Right.first; };
} else {
return
[this](const_reference _Left, const_reference _Right) { return _Key_equal(_Left.first, _Right.first); };
}
}

void _Erase_dupes_if_not_multi() {
if constexpr (_IsUnique) {
auto _Sorted_view = _View_to_mutate();
const auto _New_last = _RANGES unique(_Sorted_view, [this](const_reference _Left, const_reference _Right) {
return this->_Key_equal(_Left.first, _Right.first);
}).begin();
const auto _New_last = _RANGES unique(_Sorted_view, _Erase_dupes_if_not_multi_pred()).begin();

_Data.keys.erase(_New_last._Key_it, _Data.keys.end());
_Data.values.erase(_New_last._Mapped_it, _Data.values.end());
Expand Down
15 changes: 11 additions & 4 deletions stl/inc/flat_set
Original file line number Diff line number Diff line change
Expand Up @@ -705,13 +705,20 @@ private:
}
}

auto _Erase_dupes_if_not_multi_pred() {
Comment thread
StephanTLavavej marked this conversation as resolved.
_STL_INTERNAL_STATIC_ASSERT(_IsUnique);
if constexpr (_Equivalence_is_equality<_Keylt, _Kty>) {
return equal_to<>{};
} else {
return
[this](const _Kty& _Lhs, const _Kty& _Rhs) { return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs); };
}
}

void _Erase_dupes_if_not_multi() {
if constexpr (_IsUnique) {
const auto _Equivalent = [this](const _Kty& _Lhs, const _Kty& _Rhs) {
return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs);
};
const auto _End = _Mycont.end();
_Mycont.erase(_STD unique(_Mycont.begin(), _End, _Equivalent), _End);
_Mycont.erase(_STD unique(_Mycont.begin(), _End, _Erase_dupes_if_not_multi_pred()), _End);
}
}

Expand Down
6 changes: 6 additions & 0 deletions stl/inc/xstring
Original file line number Diff line number Diff line change
Expand Up @@ -3236,6 +3236,12 @@ private:

#pragma warning(pop)

#if _HAS_CXX23
template <class _Elem, class _Traits, class _Alloc>
constexpr bool _Equivalence_is_equality_impl<basic_string<_Elem, _Traits, _Alloc>> =
_Is_implementation_handled_char_traits<_Traits>;
#endif // _HAS_CXX23

#if _HAS_CXX17
template <class _Iter, class _Alloc = allocator<_Iter_value_t<_Iter>>,
enable_if_t<conjunction_v<_Is_iterator<_Iter>, _Is_allocator<_Alloc>>, int> = 0>
Expand Down
10 changes: 10 additions & 0 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -7920,6 +7920,16 @@ _NODISCARD constexpr bool _Mul_overflow(const _Int _Left, const _Int _Right, _In
}
#endif // _HAS_CXX17

#if _HAS_CXX23
template <class _Ty>
constexpr bool _Equivalence_is_equality_impl = is_integral_v<_Ty> || is_pointer_v<_Ty>;

// For ranges::less and ranges::greater, see N5032 [range.cmp]/9, [concept.totallyordered]/1.1, [cmp.concept]/1.2.
template <class _Compare, class _Key>
constexpr bool _Equivalence_is_equality =
_Is_any_of_v<_Compare, _RANGES less, _RANGES greater>
|| (_Is_any_of_v<_Compare, less<>, less<_Key>, greater<>, greater<_Key>> && _Equivalence_is_equality_impl<_Key>);
#endif // _HAS_CXX23
_STD_END

// TRANSITION, non-_Ugly attribute tokens
Expand Down