1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
6 #define BASE_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
7
8 #include <memory>
9
10 #include "base/memory/raw_ptr.h"
11
12 namespace base {
13
14 // This transparent comparator allows to lookup by raw pointer in
15 // a container of unique pointers. This functionality is based on C++14
16 // extensions to std::set/std::map interface, and can also be used
17 // with base::flat_set/base::flat_map.
18 //
19 // Example usage:
20 // Foo* foo = ...
21 // std::set<std::unique_ptr<Foo>, base::UniquePtrComparator> set;
22 // set.insert(std::unique_ptr<Foo>(foo));
23 // ...
24 // auto it = set.find(foo);
25 // EXPECT_EQ(foo, it->get());
26 //
27 // You can find more information about transparent comparisons here:
28 // http://en.cppreference.com/w/cpp/utility/functional/less_void
29 struct UniquePtrComparator {
30 using is_transparent = int;
31
32 template <typename T, class Deleter = std::default_delete<T>>
operatorUniquePtrComparator33 bool operator()(const std::unique_ptr<T, Deleter>& lhs,
34 const std::unique_ptr<T, Deleter>& rhs) const {
35 return lhs < rhs;
36 }
37
38 template <typename T, class Deleter = std::default_delete<T>>
operatorUniquePtrComparator39 bool operator()(const T* lhs, const std::unique_ptr<T, Deleter>& rhs) const {
40 return lhs < rhs.get();
41 }
42
43 template <typename T, class Deleter = std::default_delete<T>>
operatorUniquePtrComparator44 bool operator()(const std::unique_ptr<T, Deleter>& lhs, const T* rhs) const {
45 return lhs.get() < rhs;
46 }
47 };
48
49 // UniquePtrMatcher is useful for finding an element in a container of
50 // unique_ptrs when you have the raw pointer.
51 //
52 // Example usage:
53 // std::vector<std::unique_ptr<Foo>> vector;
54 // Foo* element = ...
55 // auto iter = base::ranges::find_if(vector, MatchesUniquePtr(element));
56 //
57 // Example of erasing from container:
58 // EraseIf(v, MatchesUniquePtr(element));
59 //
60 template <class T, class Deleter = std::default_delete<T>>
61 struct UniquePtrMatcher {
UniquePtrMatcherUniquePtrMatcher62 explicit UniquePtrMatcher(T* t) : t_(t) {}
63
operatorUniquePtrMatcher64 bool operator()(const std::unique_ptr<T, Deleter>& o) {
65 return o.get() == t_;
66 }
67
68 private:
69 const raw_ptr<T, DanglingUntriaged> t_;
70 };
71
72 template <class T, class Deleter = std::default_delete<T>>
MatchesUniquePtr(T * t)73 UniquePtrMatcher<T, Deleter> MatchesUniquePtr(T* t) {
74 return UniquePtrMatcher<T, Deleter>(t);
75 }
76
77 } // namespace base
78
79 #endif // BASE_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
80