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..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_ |