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