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