Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 48 additions & 39 deletions libcxx/include/__flat_map/flat_multimap.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,41 +408,45 @@ class flat_multimap {
}

// iterators
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept {
return iterator(__containers_.keys.begin(), __containers_.values.begin());
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept {
return const_iterator(__containers_.keys.begin(), __containers_.values.begin());
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept {
return iterator(__containers_.keys.end(), __containers_.values.end());
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept {
return const_iterator(__containers_.keys.end(), __containers_.values.end());
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept {
return reverse_iterator(end());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(end());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept {
return reverse_iterator(begin());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(begin());
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept {
return begin();
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept {
return end();
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator(end());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept {
return const_reverse_iterator(begin());
}

Expand All @@ -451,11 +455,11 @@ class flat_multimap {
return __containers_.keys.empty();
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept {
return __containers_.keys.size();
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept {
return std::min<size_type>(__containers_.keys.max_size(), __containers_.values.max_size());
}

Expand Down Expand Up @@ -578,7 +582,7 @@ class flat_multimap {
insert(sorted_equivalent, __il.begin(), __il.end());
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 containers extract() && {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 containers extract() && {
auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; });
auto __ret = std::move(__containers_);
return __ret;
Expand Down Expand Up @@ -644,118 +648,123 @@ class flat_multimap {
}

// observers
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const {
return value_compare(__compare_);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const key_container_type& keys() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const key_container_type& keys() const noexcept {
return __containers_.keys;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_container_type& values() const noexcept {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_container_type&
values() const noexcept {
return __containers_.values;
}

// map operations
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) {
return __find_impl(*this, __x);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const {
return __find_impl(*this, __x);
}

template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) {
return __find_impl(*this, __x);
}

template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const {
return __find_impl(*this, __x);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const {
auto [__first, __last] = equal_range(__x);
return __last - __first;
}

template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const {
auto [__first, __last] = equal_range(__x);
return __last - __first;
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const {
return find(__x) != end();
}

template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const {
return find(__x) != end();
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) {
return __lower_bound<iterator>(*this, __x);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator
lower_bound(const key_type& __x) const {
return __lower_bound<const_iterator>(*this, __x);
}

template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) {
return __lower_bound<iterator>(*this, __x);
}

template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const {
return __lower_bound<const_iterator>(*this, __x);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) {
return __upper_bound<iterator>(*this, __x);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator
upper_bound(const key_type& __x) const {
return __upper_bound<const_iterator>(*this, __x);
}

template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) {
return __upper_bound<iterator>(*this, __x);
}

template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const {
return __upper_bound<const_iterator>(*this, __x);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator> equal_range(const key_type& __x) {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator>
equal_range(const key_type& __x) {
return __equal_range_impl(*this, __x);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
equal_range(const key_type& __x) const {
return __equal_range_impl(*this, __x);
}

template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator> equal_range(const _Kp& __x) {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator>
equal_range(const _Kp& __x) {
return __equal_range_impl(*this, __x);
}
template <class _Kp>
requires __is_compare_transparent
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
equal_range(const _Kp& __x) const {
return __equal_range_impl(*this, __x);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason why operator== and <=> are not marked?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compiler is already issuing a diagnostic, so we decided not to mark the operators.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,97 @@
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
// REQUIRES: std-at-least-c++23

// <flat_map>

// class flat_multimap

// [[nodiscard]] bool empty() const noexcept;
// Check that functions are marked [[nodiscard]]

#include <flat_map>
#include <utility>

template <typename T>
struct TransparentKey {
T t;

constexpr explicit operator T() const { return t; }
};

struct TransparentCompare {
using is_transparent = void; // This makes the comparator transparent

template <typename T>
constexpr bool operator()(const T& t, const TransparentKey<T>& transparent) const {
return t < transparent.t;
}

template <typename T>
constexpr bool operator()(const TransparentKey<T>& transparent, const T& t) const {
return transparent.t < t;
}

template <typename T>
constexpr bool operator()(const T& t1, const T& t2) const {
return t1 < t2;
}
};

void test() {
std::flat_multimap<int, int, TransparentCompare> mm;
const std::flat_multimap<int, int, TransparentCompare> cmm;

mm.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

mm.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

cmm.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

mm.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

mm.key_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.value_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.keys(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.values(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

int key = 0;
TransparentKey<int> tkey;

mm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

mm.count(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.count(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

mm.contains(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.contains(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

mm.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

mm.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}

void f() {
std::flat_multimap<int, int> c;
c.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
mm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
cmm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
}
Loading