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