 Chromium Code Reviews
 Chromium Code Reviews Issue 2829083002:
  Add constexpr TaskTraits constructor.  (Closed)
    
  
    Issue 2829083002:
  Add constexpr TaskTraits constructor.  (Closed) 
  | 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_ |