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