11#ifndef __AUDACITY_TYPE_SWITCH__
12#define __AUDACITY_TYPE_SWITCH__
25 std::tuple<
const Functions &...>;
34template<
typename R,
typename ArgumentTypes,
typename Funs,
typename... Args>
36 static_assert(!Null_v<ArgumentTypes>);
47 if constexpr (std::is_void_v<R>)
55 template<
typename Fs,
typename Wrapped>
struct Combine {
60 using Next =
typename Wrapped::type;
63 enum :
unsigned {
SetUsed = Next::SetUsed << 1 };
70 std::forward<Args>(args)...);
75 template<
typename BaseClass,
typename NextBase>
struct CombineOp {
77 std::is_const_v<BaseClass> == std::is_const_v<ArgumentType>);
79 using Compatible = std::is_base_of<BaseClass, ArgumentType>;
89 BaseClass &
object,
const Functions &functions, Args&&... args)
91 return std::get<0>(functions)(
92 object, std::forward<Args>(args)...);
99 using Next =
typename Wrapped::type;
101 enum :
unsigned {
SetUsed = (Next::SetUsed << 1) | 1u };
106 BaseClass &
object,
const Functions &functions, Args&&... args)
111 const auto next = [&](){
return
113 std::forward<Args>(args)...); };
114 return std::get<0>(functions)(next)(
115 object, std::forward<Args>(args)...);
123 if constexpr(std::is_void_v<R>)
return;
else return R{};
125 using curried = std::is_invocable<F, Dummy&&>;
130 using Case1 = std::conjunction<Compatible, curried, Case1_>;
132 static constexpr bool value = std::is_invocable_v<
133 std::invoke_result_t<F, Dummy &&>, BaseClass&, Args&&...>;
139 Compatible, std::negation<curried>,
140 std::is_invocable<F, BaseClass&, Args&&...>
145 using type =
typename NextBase::type;
147 using type =
typename std::disjunction<Case1, Case2, Default>::type;
162 typename R,
typename ArgumentTypes,
typename Functions,
typename... Args>
164 typename Executor<R, ArgumentTypes, Functions, Args...>::type;
167template<
typename R,
typename Exec,
typename ObjectTypes>
171 template<
typename Object,
typename Functions,
typename... Args>
172 R
operator ()(Object &
object,
const Functions &functions, Args&&...)
177 if constexpr (std::is_void_v<R>)
183 template<
typename ObjectType,
typename Recur>
struct Op {
184 template<
typename Object,
typename Functions,
typename... Args>
185 R
operator ()(Object &
object,
const Functions &functions, Args&&... args)
188 if (
const auto pObject =
dynamic_cast<ObjectType*
>(&
object))
190 return Exec{}(*pObject, functions, std::forward<Args>(args)...);
193 return Recur{}(object, functions, std::forward<Args>(args)...);
197 template<
typename Object,
typename Functions,
typename... Args>
198 R
operator ()(Object &
object,
const Functions &functions, Args&&... args)
201 return fn(
object, functions, std::forward<Args>(args)...);
207 return std::integral_constant<unsigned, (Executors::SetUsed | ...)>{};
212 std::index_sequence<Is...>,
const TupleLike &functions) {
213 return std::forward_as_tuple(std::get<Is>(functions)...);
218 typename ObjectTypes,
223 static_assert(!Null_v<ObjectTypes>);
234 static_assert(std::is_same_v<
235 std::integral_constant<unsigned, AllBits>,
238 "Uncallable case in TypeSwitch");
242 Object &
object,
const TupleLike &functions,
243 Args&&... args)
const {
247 std::forward<Args>(args)...);
260 std::is_polymorphic_v<Head_t<TypeList>> &&
261 detail::RootTypeCheck_v<TypeList> &&
263 (Every_v<Fn<std::is_const>,
TypeList> ||
264 NotAny_v<Fn<std::is_const>,
TypeList>);
315 -> std::enable_if_t<TypeListCheck_v<Types>, R>
319 object, functions, std::forward<Args>(args)...);
329 typename ...Functions
333 return Dispatch<R, Types>(
object, std::forward_as_tuple(functions...));
Functions and classes that generate callable objects.
Extraction of sub-tuples of std::tuple (or other tuple-like classes)
Metaprogramming utilities for manipulating lists of types.
std::vector< Type > Types
auto ForwardNext(Tuple &&tuple)
Forwarding of the tail of a tuple.
Utilities for compile-time type manipulation. Some terminology as in Lisp.
typename NonEmptyTails< TypeList >::type NonEmptyTails_t
typename LeftFold< Op, TypeList, Initial >::type LeftFold_t
typename Tail< TypeList >::type Tail_t
Call< Predicate, T > Is
Apply a metapredicate to a type.
typename Apply< Template, TypeList >::type Apply_t
typename MapList< Metafunction, TypeList >::type MapList_t
typename Head< TypeList >::type Head_t
typename RightFoldList< Op, TypeList, Initial >::type RightFoldList_t
Apply_t< FunctionTupleType, Functions > FunctionTuple
auto MakeFunctionTuple(std::index_sequence< Is... >, const TupleLike &functions)
std::tuple< const Functions &... > FunctionTupleType
constexpr bool RootTypeCheck_v
typename Executor< R, ArgumentTypes, Functions, Args... >::type Executor_t
Synthesize a function appropriate for ArgumentType.
auto VDispatch(Head_t< Types > &object, const Functions &...functions)
auto Dispatch(Head_t< Types > &object, const TupleLike &functions, Args &&... args) -> std::enable_if_t< TypeListCheck_v< Types >, R >
constexpr bool TypeListCheck_v
Delays expansion of nested alias rest; so Tail<Nil> is legal.
static constexpr bool value
typename NextBase::type type
R operator()(BaseClass &object, const Functions &functions, Args &&... args) const
Ignore the remaining functions and call the first only.
typename Wrapped::type Next
R operator()(BaseClass &object, const Functions &functions, Args &&... args) const
std::conjunction< Compatible, curried, Case1_ > Case1
typename std::disjunction< Case1, Case2, Default >::type type
std::is_invocable< F, Dummy && > curried
std::is_base_of< BaseClass, ArgumentType > Compatible
Whether upcast of ArgumentType* to BaseClass* works.
No BaseClass of ArgumentType is acceptable to the first function.
R operator()(ArgumentType &object, const Functions &functions, Args &&... args) const
Ignore the first, inapplicable function and try others.
typename Wrapped::type Next
typename LeftFold_t< CombineOp, ArgumentTypes, Transparent >::type type
FunctionTuple< Fs > Functions
R operator()(ArgumentType &, const Functions &, Args &&...) const
No functions matched, so do nothing.
FunctionTuple< Nil > Functions
Metafunction implementing TypeSwitch.
typename RightFoldList_t< Combine, Funs, NoOp >::type type
Head_t< ArgumentTypes > ArgumentType
R operator()(Object &object, const Functions &functions, Args &&...) const
R operator()(Object &object, const Functions &functions, Args &&... args) const
R operator()(Object &object, const Functions &functions, Args &&... args) const
MapList_t< Fn< Executor_ >, ObjectTypes > Executors
R operator()(Object &object, const TupleLike &functions, Args &&... args) const
Executor_t< R, Tail, Functions, Args... > Executor_
Apply_t< Callable::OverloadSet, Executors > Exec
Head_t< ObjectTypes > Object
constexpr auto operator()()