• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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_MEMORY_VALUES_EQUIVALENT_H_
6 #define BASE_MEMORY_VALUES_EQUIVALENT_H_
7 
8 #include <functional>
9 #include <memory>
10 
11 #include "base/memory/scoped_refptr.h"
12 
13 namespace base {
14 
15 // Compares two pointers for equality, returns the dereferenced value comparison
16 // if both are non-null.
17 // Behaves like std::optional<T>::operator==(const std::optional<T>&) but for
18 // pointers, with an optional predicate.
19 // If `p` is specified, `p(const T& x, const T& y)` should return whether `x`
20 // and `y` are equal. It's called with `(*a, *b)` when `a != b && a && b`.
21 template <typename T, typename Predicate = std::equal_to<>>
22 bool ValuesEquivalent(const T* a, const T* b, Predicate p = {}) {
23   if (a == b)
24     return true;
25   if (!a || !b)
26     return false;
27   return p(*a, *b);
28 }
29 
30 // Specialize for smart pointers like std::unique_ptr and base::scoped_refptr
31 // that provide a T* get() method.
32 // Example usage:
33 //   struct Example {
34 //     std::unique_ptr<Child> child;
35 //     bool operator==(const Example& other) const {
36 //       return base::ValuesEquivalent(child, other.child);
37 //     }
38 //   };
39 template <typename T,
40           typename Predicate = std::equal_to<>,
41           std::enable_if_t<
42               std::is_pointer_v<decltype(std::declval<T>().get())>>* = nullptr>
43 bool ValuesEquivalent(const T& x, const T& y, Predicate p = {}) {
44   return ValuesEquivalent(x.get(), y.get(), std::move(p));
45 }
46 
47 // Specialize for smart pointers like blink::Persistent and blink::Member that
48 // provide a T* Get() method.
49 // Example usage:
50 //   namespace blink {
51 //   struct Example : public GarbageCollected<Example> {
52 //     Member<Child> child;
53 //     bool operator==(const Example& other) const {
54 //       return base::ValuesEquivalent(child, other.child);
55 //     }
56 //     void Trace(Visitor*) const;
57 //   };
58 //   }  // namespace blink
59 template <typename T,
60           typename Predicate = std::equal_to<>,
61           std::enable_if_t<
62               std::is_pointer_v<decltype(std::declval<T>().Get())>>* = nullptr>
63 bool ValuesEquivalent(const T& x, const T& y, Predicate p = {}) {
64   return ValuesEquivalent(x.Get(), y.Get(), std::move(p));
65 }
66 
67 }  // namespace base
68 
69 #endif  // BASE_MEMORY_VALUES_EQUIVALENT_H_
70