OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 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_FUNCTIONAL_H_ |
| 6 #define BASE_FUNCTIONAL_H_ |
| 7 |
| 8 #include <functional> |
| 9 #include <utility> |
| 10 |
| 11 #include "base/type_traits.h" |
| 12 |
| 13 namespace base { |
| 14 |
| 15 namespace internal { |
| 16 |
| 17 template <typename T> |
| 18 using HasGet = decltype(std::declval<T>().get()); |
| 19 |
| 20 template <typename T> |
| 21 using HasDereference = decltype(*(std::declval<T>())); |
| 22 |
| 23 template <typename Lhs, typename Rhs> |
| 24 using HaveLess = decltype(std::declval<Lhs>() < std::declval<Rhs>()); |
| 25 |
| 26 } // namespace internal |
| 27 |
| 28 // Concepts ------------------------------------------------------------------- |
| 29 |
| 30 template <typename T> |
| 31 constexpr bool SmartPointer() { |
| 32 return is_detected_c<internal::HasGet, T>() && |
| 33 is_detected_c<internal::HasDereference, T>(); |
| 34 } |
| 35 |
| 36 template <typename Lhs, typename Rhs> |
| 37 constexpr bool Comparable() { |
| 38 return is_detected_c<internal::HaveLess, Lhs, Rhs>(); |
| 39 } |
| 40 |
| 41 // Function objects ------------------------------------------------------------ |
| 42 |
| 43 // Variation of std::less<> from C++14. |
| 44 // Needed for improved flat containers API. |
| 45 // |
| 46 // Also supports comparing smart pointers to plain pointers because this is a |
| 47 // common use case and makes sets of smart pointers much more useful. |
| 48 // Note: we have to use different enable_if techniques, because: |
| 49 // a) we want to deduce return value for common case (as the standard one) and |
| 50 // not be extremely ugly while doing so. |
| 51 // b) Some weired property doesn't allow us to use 'typename =' as a common |
| 52 // technique: |
| 53 // https://stackoverflow.com/questions/41646253/sfinae-class-member-cannot-be
-redeclared |
| 54 |
| 55 struct less { |
| 56 template <typename T, typename U, typename = enable_if_t<Comparable<T, U>()>> |
| 57 constexpr auto operator()(T&& lhs, U&& rhs) const |
| 58 -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs)) { |
| 59 return std::forward<T>(lhs) < std::forward<U>(rhs); |
| 60 } |
| 61 |
| 62 template <typename T, typename U> |
| 63 constexpr enable_if_t<SmartPointer<T>() && !SmartPointer<U>(), bool> |
| 64 operator()(const T& smart_ptr, const U& ptr) const { |
| 65 return smart_ptr.get() < ptr; |
| 66 } |
| 67 |
| 68 template <typename T, typename U> |
| 69 constexpr enable_if_t<!SmartPointer<T>() && SmartPointer<U>(), bool> |
| 70 operator()(const T& ptr, const U& smart_ptr) const { |
| 71 return ptr < smart_ptr.get(); |
| 72 } |
| 73 |
| 74 using is_transparent = int; |
| 75 }; |
| 76 |
| 77 } // base |
| 78 |
| 79 #endif // BASE_FUNCTIONAL_H_ |
OLD | NEW |