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()()