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>
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>
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, base::RawPtrTraits Traits>
operatorUniquePtrComparator44 bool operator()(const raw_ptr<T, Traits>& lhs,
45 const std::unique_ptr<T, Deleter>& rhs) const {
46 return lhs < rhs.get();
47 }
48
49 template <typename T, class Deleter>
operatorUniquePtrComparator50 bool operator()(const std::unique_ptr<T, Deleter>& lhs, const T* rhs) const {
51 return lhs.get() < rhs;
52 }
53
54 template <typename T, class Deleter, base::RawPtrTraits Traits>
operatorUniquePtrComparator55 bool operator()(const std::unique_ptr<T, Deleter>& lhs,
56 const raw_ptr<T, Traits>& rhs) const {
57 return lhs.get() < rhs;
58 }
59 };
60
61 // UniquePtrMatcher is useful for finding an element in a container of
62 // unique_ptrs when you have the raw pointer.
63 //
64 // Example usage:
65 // std::vector<std::unique_ptr<Foo>> vector;
66 // Foo* element = ...
67 // auto iter = base::ranges::find_if(vector, MatchesUniquePtr(element));
68 //
69 // Example of erasing from container:
70 // EraseIf(v, MatchesUniquePtr(element));
71 //
72 template <class T, class Deleter = std::default_delete<T>>
73 struct UniquePtrMatcher {
UniquePtrMatcherUniquePtrMatcher74 explicit UniquePtrMatcher(T* t) : t_(t) {}
75
operatorUniquePtrMatcher76 bool operator()(const std::unique_ptr<T, Deleter>& o) {
77 return o.get() == t_;
78 }
79
80 private:
81 const raw_ptr<T, DanglingUntriaged> t_;
82 };
83
84 template <class T, class Deleter = std::default_delete<T>>
MatchesUniquePtr(T * t)85 UniquePtrMatcher<T, Deleter> MatchesUniquePtr(T* t) {
86 return UniquePtrMatcher<T, Deleter>(t);
87 }
88
89 template <class T,
90 class Deleter = std::default_delete<T>,
91 base::RawPtrTraits Traits = base::RawPtrTraits::kEmpty>
MatchesUniquePtr(const raw_ptr<T,Traits> & t)92 UniquePtrMatcher<T, Deleter> MatchesUniquePtr(const raw_ptr<T, Traits>& t) {
93 return UniquePtrMatcher<T, Deleter>(t.get());
94 }
95
96 } // namespace base
97
98 #endif // BASE_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
99