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..7149924d67130a7ad91fba2488ad45bae24bacfd |
--- /dev/null |
+++ b/base/task_scheduler/task_traits_details.h |
@@ -0,0 +1,135 @@ |
+// 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 {}; |
+ |
+// ArgsAreConvertible<CheckedType, ArgTypes...>::value is true iff all types in |
+// ArgTypes are convertible to CheckedType. |
+template <class...> |
+struct ArgsAreConvertible : std::true_type {}; |
+template <class CheckedType, class FirstArgType, class... ArgTypes> |
+struct ArgsAreConvertible<CheckedType, FirstArgType, ArgTypes...> |
gab
2017/04/28 18:15:43
Unused
fdoray
2017/04/28 18:40:36
Done.
|
+ : std::conditional<std::is_convertible<FirstArgType, CheckedType>::value, |
+ ArgsAreConvertible<CheckedType, ArgTypes...>, |
+ std::false_type>::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( |
+ CallSecondTag, |
+ 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. |
gab
2017/04/28 18:15:42
Expand comment to explain what this is used for.
fdoray
2017/04/28 18:40:36
Done.
|
+template <class...> |
+struct InitTypes {}; |
+ |
+} // namespace internal |
+} // namespace base |
+ |
+#endif // BASE_TASK_SCHEDULER_TASK_TRAITS_DETAILS_H_ |