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_TASK_SCHEDULER_TASK_TRAITS_DETAILS_H_ |
| 6 #define BASE_TASK_SCHEDULER_TASK_TRAITS_DETAILS_H_ |
| 7 |
| 8 #include <type_traits> |
| 9 #include <utility> |
| 10 |
| 11 namespace base { |
| 12 namespace internal { |
| 13 |
| 14 // HasArgOfType<CheckedType, ArgTypes...>::value is true iff a type in ArgTypes |
| 15 // matches CheckedType. |
| 16 template <class...> |
| 17 struct HasArgOfType : std::false_type {}; |
| 18 template <class CheckedType, class FirstArgType, class... ArgTypes> |
| 19 struct HasArgOfType<CheckedType, FirstArgType, ArgTypes...> |
| 20 : std::conditional<std::is_same<CheckedType, FirstArgType>::value, |
| 21 std::true_type, |
| 22 HasArgOfType<CheckedType, ArgTypes...>>::type {}; |
| 23 |
| 24 // ArgsAreConvertible<CheckedType, ArgTypes...>::value is true iff all types in |
| 25 // ArgTypes are convertible to CheckedType. |
| 26 template <class...> |
| 27 struct ArgsAreConvertible : std::true_type {}; |
| 28 template <class CheckedType, class FirstArgType, class... ArgTypes> |
| 29 struct ArgsAreConvertible<CheckedType, FirstArgType, ArgTypes...> |
| 30 : std::conditional<std::is_convertible<FirstArgType, CheckedType>::value, |
| 31 ArgsAreConvertible<CheckedType, ArgTypes...>, |
| 32 std::false_type>::type {}; |
| 33 |
| 34 // When the following call is made: |
| 35 // GetValueFromArgListImpl(CallFirstTag(), GetterType(), args...); |
| 36 // The compiler prefers using the first overload of GetValueFromArgListImpl(), |
| 37 // because the type of the first argument matches exactly. This overload returns |
| 38 // getter.GetValueFromArg(first_arg), where |first_arg| is the first element in |
| 39 // |args|. If getter.GetValueFromArg(first_arg) isn't defined, the compiler uses |
| 40 // the second or the third overload instead (depending on whether |args| is |
| 41 // empty). The second overload discards |first_arg| and makes a recursive call |
| 42 // to GetValueFromArgListImpl() with CallFirstTag() as first argument. The third |
| 43 // overload returns getter.GetDefaultValue(). |
| 44 |
| 45 // Tag dispatching. |
| 46 struct CallSecondTag {}; |
| 47 struct CallFirstTag : CallSecondTag {}; |
| 48 |
| 49 // Overload 1: Get value from first argument. Check that no argument in |args| |
| 50 // has the same type as |first_arg|. |
| 51 template <class GetterType, |
| 52 class FirstArgType, |
| 53 class... ArgTypes, |
| 54 class TestGetValueFromArgDefined = |
| 55 decltype(std::declval<GetterType>().GetValueFromArg( |
| 56 std::declval<FirstArgType>()))> |
| 57 constexpr typename GetterType::ValueType GetValueFromArgListImpl( |
| 58 CallFirstTag, |
| 59 GetterType getter, |
| 60 const FirstArgType& first_arg, |
| 61 const ArgTypes&... args) { |
| 62 static_assert(!HasArgOfType<FirstArgType, ArgTypes...>::value, |
| 63 "Multiple arguments of the same type were provided to the " |
| 64 "constructor of TaskTraits."); |
| 65 return getter.GetValueFromArg(first_arg); |
| 66 } |
| 67 |
| 68 // Overload 2: Discard first argument. |
| 69 template <class GetterType, class FirstArgType, class... ArgTypes> |
| 70 constexpr typename GetterType::ValueType GetValueFromArgListImpl( |
| 71 CallSecondTag, |
| 72 GetterType getter, |
| 73 const FirstArgType&, |
| 74 const ArgTypes&... args) { |
| 75 return GetValueFromArgListImpl(CallFirstTag(), getter, args...); |
| 76 } |
| 77 |
| 78 // Overload 3: Default value. |
| 79 template <class GetterType> |
| 80 constexpr typename GetterType::ValueType GetValueFromArgListImpl( |
| 81 CallSecondTag, |
| 82 GetterType getter) { |
| 83 return getter.GetDefaultValue(); |
| 84 } |
| 85 |
| 86 // If there is an argument |arg_of_type| of type Getter::ArgType in |args|, |
| 87 // returns getter.GetValueFromArg(arg_of_type). If there are more than one |
| 88 // argument of type Getter::ArgType in |args|, generates a compile-time error. |
| 89 // Otherwise, returns getter.GetDefaultValue(). |
| 90 // |
| 91 // |getter| must provide: |
| 92 // |
| 93 // ValueType: |
| 94 // The return type of GetValueFromArgListImpl(). |
| 95 // |
| 96 // ArgType: |
| 97 // The type of the argument from which GetValueFromArgListImpl() derives its |
| 98 // return value. |
| 99 // |
| 100 // ValueType GetValueFromArg(ArgType): |
| 101 // Converts an argument of type ArgType into a value returned by |
| 102 // GetValueFromArgListImpl(). |
| 103 // |
| 104 // ValueType GetDefaultValue(): |
| 105 // Returns the value returned by GetValueFromArgListImpl() if none of its |
| 106 // arguments is of type ArgType. |
| 107 template <class GetterType, class... ArgTypes> |
| 108 constexpr typename GetterType::ValueType GetValueFromArgList( |
| 109 GetterType getter, |
| 110 const ArgTypes&... args) { |
| 111 return GetValueFromArgListImpl(CallFirstTag(), getter, args...); |
| 112 } |
| 113 |
| 114 template <typename ArgType> |
| 115 struct BooleanArgGetter { |
| 116 using ValueType = bool; |
| 117 constexpr ValueType GetValueFromArg(ArgType) const { return true; } |
| 118 constexpr ValueType GetDefaultValue() const { return false; } |
| 119 }; |
| 120 |
| 121 template <typename ArgType, ArgType DefaultValue> |
| 122 struct EnumArgGetter { |
| 123 using ValueType = ArgType; |
| 124 constexpr ValueType GetValueFromArg(ArgType arg) const { return arg; } |
| 125 constexpr ValueType GetDefaultValue() const { return DefaultValue; } |
| 126 }; |
| 127 |
| 128 } // namespace internal |
| 129 } // namespace base |
| 130 |
| 131 #endif // BASE_TASK_SCHEDULER_TASK_TRAITS_DETAILS_H_ |
OLD | NEW |