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