| 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_
|
|
|