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..62507773c320ec937db0d33949db9a1b1643424d |
--- /dev/null |
+++ b/base/task_scheduler/task_traits_details.h |
@@ -0,0 +1,97 @@ |
+// 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 { |
+ |
gab
2017/04/25 17:48:15
Remove this empty line (consistent with EOF)
fdoray
2017/04/26 17:20:33
Done.
|
+namespace internal { |
+ |
+// CheckNoArgOfType() generates a compile-time error if it receives an argument |
+// of type UnwantedType. The second overload checks the type of the first |
+// argument and makes a recursive call with the remaining arguments. The first |
+// overload takes no argument and is used to end the recursion. Both overloads |
+// return a bool because it is invalid for a constexpr function to return void. |
+template <class UnwantedType> |
+constexpr bool CheckNoArgOfType() { |
+ return true; |
+} |
+ |
+template <class UnwantedType, class FirstArgType, class... ArgTypes> |
+constexpr bool CheckNoArgOfType(const FirstArgType&, const ArgTypes&... args) { |
etipdoray
2017/04/24 20:22:02
CheckNoArgOfType can be implemented without recurs
fdoray
2017/04/26 17:20:33
Done.
|
+ static_assert(!std::is_same<UnwantedType, FirstArgType>::value, |
etipdoray
2017/04/24 20:22:02
It would be best to check instead if the associate
fdoray
2017/04/26 17:20:33
not possible in c++11
|
+ "Multiple arguments of the same type were provided to the " |
+ "constructor of TaskTraits."); |
+ return CheckNoArgOfType<UnwantedType>(args...); |
+} |
+ |
+// When the following call is made: |
+// GetValueFromArgList(CallFirstTag(), GetterType(), args...); |
+// The compiler prefers using the 3rd overload of GetValueFromArgList(), because |
+// the type of the first argument matches exactly. That overload uses |
+// Getter::operator()(FirstArgType) to extract a value from |first_arg|. If |
+// Getter::operator()(FirstArgType) isn't defined, the compiler uses the first |
+// or the second overload instead (depending on whether |args| is empty). The |
+// first overload returns a default value obtained from Getter::operator()(). |
+// The second overload discards |first_arg| and calls back GetValueFromArgList() |
+// with CallFirstTag() as first argument. |
+struct CallSecondTag {}; |
+struct CallFirstTag : CallSecondTag {}; |
+ |
+// Overload 1: Default value. |
+template <class GetterType> |
+constexpr auto GetValueFromArgList(CallSecondTag, GetterType getter) |
gab
2017/04/25 17:48:15
I think
constexpr GetterType GetValueFromArgList(
fdoray
2017/04/26 17:20:33
Done.
|
+ -> decltype(getter()) { |
+ return getter(); |
+} |
+ |
+// Overload 2: Discard first argument. |
+template <class GetterType, class FirstArgType, class... ArgTypes> |
+constexpr auto GetValueFromArgList(CallSecondTag, |
+ GetterType getter, |
+ const FirstArgType&, |
+ const ArgTypes&... args) |
+ -> decltype(GetValueFromArgList(CallFirstTag(), getter, args...)) { |
gab
2017/04/25 17:48:15
Actually, isn't the return value of these 3 method
fdoray
2017/04/26 17:20:33
Done.
|
+ return GetValueFromArgList(CallFirstTag(), getter, args...); |
+} |
+ |
+// Overload 3: Get value from first argument. Check that no argument in |args| |
gab
2017/04/25 17:48:15
Since the intent is for this one to match first an
fdoray
2017/04/26 17:20:33
Done.
|
+// has the same type as |first_arg|. |
+template <class GetterType, |
+ class FirstArgType, |
+ class... ArgTypes, |
+ class Instantiation = decltype( |
+ std::declval<GetterType>()(std::declval<FirstArgType>()))> |
gab
2017/04/25 17:48:15
Document in meta-comment of this file what GetterT
fdoray
2017/04/26 17:20:33
Done.
|
+constexpr typename GetterType::ValueType GetValueFromArgList( |
+ CallFirstTag, |
+ GetterType getter, |
+ const FirstArgType& first_arg, |
+ const ArgTypes&... args) { |
+ // CheckNoArgOfType() is invoked as part of a comma operator statement to |
+ // avoid an unused return value warning. |
+ return CheckNoArgOfType<FirstArgType>(args...), getter(first_arg); |
+} |
+ |
+template <typename ArgType> |
+struct BooleanArgGetter { |
+ using ValueType = bool; |
+ constexpr ValueType operator()(ArgType) const { return true; } |
+ constexpr ValueType operator()() const { return false; } |
+}; |
+ |
+template <typename ArgType, ArgType DefaultValue> |
+struct EnumArgGetter { |
+ using ValueType = ArgType; |
+ constexpr ValueType operator()(ArgType arg) const { return arg; } |
+ constexpr ValueType operator()() const { return DefaultValue; } |
+}; |
+ |
+} // namespace internal |
+} // namespace base |
+ |
+#endif // BASE_TASK_SCHEDULER_TASK_TRAITS_DETAILS_H_ |