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