Chromium Code Reviews| Index: base/task_scheduler/task_traits_details.h |
| diff --git a/base/task_scheduler/task_traits_details.h b/base/task_scheduler/task_traits_details.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..52f23c3a2f12b3d4a5bebf039caa514f11bd30a4 |
| --- /dev/null |
| +++ b/base/task_scheduler/task_traits_details.h |
| @@ -0,0 +1,127 @@ |
| +// 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_TASK_SCHEDULER_TASK_TRAITS_DETAILS_H_ |
| +#define BASE_TASK_SCHEDULER_TASK_TRAITS_DETAILS_H_ |
| + |
| +#include <type_traits> |
| +#include <utility> |
| + |
| +namespace base { |
| +namespace internal { |
| + |
| +// HasArgOfType<CheckedType, ArgTypes...>::value is true iff a type in ArgTypes |
| +// matches CheckedType. |
| +template <class...> |
| +struct HasArgOfType : std::false_type {}; |
| +template <class CheckedType, class FirstArgType, class... ArgTypes> |
| +struct HasArgOfType<CheckedType, FirstArgType, ArgTypes...> |
| + : std::conditional<std::is_same<CheckedType, FirstArgType>::value, |
| + std::true_type, |
| + HasArgOfType<CheckedType, ArgTypes...>>::type {}; |
| + |
| +// When the following call is made: |
| +// GetValueFromArgListImpl(CallFirstTag(), GetterType(), args...); |
| +// The compiler prefers using the first overload of GetValueFromArgListImpl(), |
| +// because the type of the first argument matches exactly. This overload returns |
| +// getter.GetValueFromArg(first_arg), where |first_arg| is the first element in |
| +// |args|. If getter.GetValueFromArg(first_arg) isn't defined, the compiler uses |
| +// the second or the third overload instead (depending on whether |args| is |
| +// empty). The second overload discards |first_arg| and makes a recursive call |
| +// to GetValueFromArgListImpl() with CallFirstTag() as first argument. The third |
| +// overload returns getter.GetDefaultValue(). |
| + |
| +// Tag dispatching. |
| +struct CallSecondTag {}; |
| +struct CallFirstTag : CallSecondTag {}; |
| + |
| +// Overload 1: Get value from first argument. Check that no argument in |args| |
| +// has the same type as |first_arg|. |
| +template <class GetterType, |
| + class FirstArgType, |
| + class... ArgTypes, |
| + class TestGetValueFromArgDefined = |
| + decltype(std::declval<GetterType>().GetValueFromArg( |
| + std::declval<FirstArgType>()))> |
| +constexpr typename GetterType::ValueType GetValueFromArgListImpl( |
| + CallFirstTag, |
| + GetterType getter, |
| + const FirstArgType& first_arg, |
| + const ArgTypes&... args) { |
| + static_assert(!HasArgOfType<FirstArgType, ArgTypes...>::value, |
| + "Multiple arguments of the same type were provided to the " |
| + "constructor of TaskTraits."); |
| + return getter.GetValueFromArg(first_arg); |
| +} |
| + |
| +// Overload 2: Discard first argument. |
| +template <class GetterType, class FirstArgType, class... ArgTypes> |
| +constexpr typename GetterType::ValueType GetValueFromArgListImpl( |
| + CallSecondTag, |
| + GetterType getter, |
| + const FirstArgType&, |
| + const ArgTypes&... args) { |
| + return GetValueFromArgListImpl(CallFirstTag(), getter, args...); |
| +} |
| + |
| +// Overload 3: Default value. |
| +template <class GetterType> |
| +constexpr typename GetterType::ValueType GetValueFromArgListImpl( |
| + CallFirstTag, |
|
gab
2017/04/28 19:00:31
I meant to reorder this to be Overload 1 so that l
fdoray
2017/05/01 17:13:10
Done.
|
| + GetterType getter) { |
| + return getter.GetDefaultValue(); |
| +} |
| + |
| +// If there is an argument |arg_of_type| of type Getter::ArgType in |args|, |
| +// returns getter.GetValueFromArg(arg_of_type). If there are more than one |
| +// argument of type Getter::ArgType in |args|, generates a compile-time error. |
| +// Otherwise, returns getter.GetDefaultValue(). |
| +// |
| +// |getter| must provide: |
| +// |
| +// ValueType: |
| +// The return type of GetValueFromArgListImpl(). |
| +// |
| +// ArgType: |
| +// The type of the argument from which GetValueFromArgListImpl() derives its |
| +// return value. |
| +// |
| +// ValueType GetValueFromArg(ArgType): |
| +// Converts an argument of type ArgType into a value returned by |
| +// GetValueFromArgListImpl(). |
| +// |
| +// ValueType GetDefaultValue(): |
| +// Returns the value returned by GetValueFromArgListImpl() if none of its |
| +// arguments is of type ArgType. |
| +template <class GetterType, class... ArgTypes> |
| +constexpr typename GetterType::ValueType GetValueFromArgList( |
| + GetterType getter, |
| + const ArgTypes&... args) { |
| + return GetValueFromArgListImpl(CallFirstTag(), getter, args...); |
| +} |
| + |
| +template <typename ArgType> |
| +struct BooleanArgGetter { |
| + using ValueType = bool; |
| + constexpr ValueType GetValueFromArg(ArgType) const { return true; } |
| + constexpr ValueType GetDefaultValue() const { return false; } |
| +}; |
| + |
| +template <typename ArgType, ArgType DefaultValue> |
| +struct EnumArgGetter { |
| + using ValueType = ArgType; |
| + constexpr ValueType GetValueFromArg(ArgType arg) const { return arg; } |
| + constexpr ValueType GetDefaultValue() const { return DefaultValue; } |
| +}; |
| + |
| +// Allows instantiation of multiple types in one statement. Used to prevent |
| +// instantiation of the constructor of TaskTraits with inappropriate argument |
| +// types. |
| +template <class...> |
| +struct InitTypes {}; |
| + |
| +} // namespace internal |
| +} // namespace base |
| + |
| +#endif // BASE_TASK_SCHEDULER_TASK_TRAITS_DETAILS_H_ |