Index: base/functional.h |
diff --git a/base/functional.h b/base/functional.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..487d59de9f3828f38f8e445ebc63049ef4baea3a |
--- /dev/null |
+++ b/base/functional.h |
@@ -0,0 +1,79 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef BASE_FUNCTIONAL_H_ |
+#define BASE_FUNCTIONAL_H_ |
+ |
+#include <functional> |
+#include <utility> |
+ |
+#include "base/type_traits.h" |
+ |
+namespace base { |
+ |
+namespace internal { |
+ |
+template <typename T> |
+using HasGet = decltype(std::declval<T>().get()); |
+ |
+template <typename T> |
+using HasDereference = decltype(*(std::declval<T>())); |
+ |
+template <typename Lhs, typename Rhs> |
+using HaveLess = decltype(std::declval<Lhs>() < std::declval<Rhs>()); |
+ |
+} // namespace internal |
+ |
+// Concepts ------------------------------------------------------------------- |
+ |
+template <typename T> |
+constexpr bool SmartPointer() { |
+ return is_detected_c<internal::HasGet, T>() && |
+ is_detected_c<internal::HasDereference, T>(); |
+} |
+ |
+template <typename Lhs, typename Rhs> |
+constexpr bool Comparable() { |
+ return is_detected_c<internal::HaveLess, Lhs, Rhs>(); |
+} |
+ |
+// Function objects ------------------------------------------------------------ |
+ |
+// Variation of std::less<> from C++14. |
+// Needed for improved flat containers API. |
+// |
+// Also supports comparing smart pointers to plain pointers because this is a |
+// common use case and makes sets of smart pointers much more useful. |
+// Note: we have to use different enable_if techniques, because: |
+// a) we want to deduce return value for common case (as the standard one) and |
+// not be extremely ugly while doing so. |
+// b) Some weired property doesn't allow us to use 'typename =' as a common |
+// technique: |
+// https://stackoverflow.com/questions/41646253/sfinae-class-member-cannot-be-redeclared |
+ |
+struct less { |
+ template <typename T, typename U, typename = enable_if_t<Comparable<T, U>()>> |
+ constexpr auto operator()(T&& lhs, U&& rhs) const |
+ -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs)) { |
+ return std::forward<T>(lhs) < std::forward<U>(rhs); |
+ } |
+ |
+ template <typename T, typename U> |
+ constexpr enable_if_t<SmartPointer<T>() && !SmartPointer<U>(), bool> |
+ operator()(const T& smart_ptr, const U& ptr) const { |
+ return smart_ptr.get() < ptr; |
+ } |
+ |
+ template <typename T, typename U> |
+ constexpr enable_if_t<!SmartPointer<T>() && SmartPointer<U>(), bool> |
+ operator()(const T& ptr, const U& smart_ptr) const { |
+ return ptr < smart_ptr.get(); |
+ } |
+ |
+ using is_transparent = int; |
+}; |
+ |
+} // base |
+ |
+#endif // BASE_FUNCTIONAL_H_ |