11#ifndef __AUDACITY_REGISTRY__
12#define __AUDACITY_REGISTRY__
65 return std::make_pair(
type,
name ) <
66 std::make_pair( other.
type, other.
name );
70 template<
typename RegistryTraits>
struct GroupItem;
71 using Path = std::vector<Identifier>;
82 :
name{ internalName }
109 static constexpr bool value = !std::is_same_v<Type, Head_t<L>>;
111 using type = std::conditional_t<
121 typename RegistryTraits::NodeTypes>>;
124 typename RegistryTraits::LeafTypes>>;
141 template<typename RegistryTraits> struct
AllTypes {
143 typename RegistryTraits::LeafTypes,
144 typename RegistryTraits::NodeTypes
151 TypeList::Every_v<TypeList::Fn<AcceptableBaseItem>,
153 TypeSwitch::TypeListCheck_v<detail::VisitedNodeTypes<RegistryTraits>> &&
154 TypeSwitch::TypeListCheck_v<detail::VisitedLeafTypes<RegistryTraits>>;
163 template<
typename Item>
166 static_assert(AcceptableBaseItem_v<ItemType>);
174 template<
typename Item>
175 inline std::unique_ptr<detail::IndirectItem<Item>>
Indirect(
176 const std::shared_ptr<Item> &ptr)
178 return std::make_unique<detail::IndirectItem<Item>>( ptr );
200 template<
typename Context,
typename Item>
203 static_assert(AcceptableBaseItem_v<ItemType>);
217 return factory(*
static_cast<Context *
>(p));
225 using BaseItem::BaseItem;
231 REGISTRIES_API
void RegisterItem(GroupItemBase ®istry,
236 BaseItem, std::unique_ptr<BaseItem>, const Identifier &
259 virtual Ordering GetOrdering()
const;
268 template<
typename RegistryTraits>
struct GroupItem;
270 template<
typename RegistryTraits>
struct Builder;
281 !std::is_same_v<T, Registry::detail::BaseItemPtr>;
289 template<
typename RegistryTraits>
291 detail::GroupItemBase, GroupItem<RegistryTraits>, const Identifier &
320 template<
typename C,
typename T>
326 ::TypeList::HasBaseIn_v<ActualItem_t<Item>,
TypeList>;
331 template<
typename RegistryTraits,
typename Item>
336 template<
typename RegistryTraits>
338 using Context =
typename RegistryTraits::ComputedItemContextType;
340 template<
typename ItemType>
342 static_assert(AcceptableType_v<RegistryTraits, ItemType>);
347 template<
typename Factory,
349 typename std::invoke_result_t<Factory, Context&>::element_type
352 static_assert(AcceptableType_v<RegistryTraits, ItemType>);
353 return std::make_unique<ComputedItem<Context, ItemType>>(
factory);
356 template<
typename ItemType>
358 static_assert(AcceptableType_v<RegistryTraits, ItemType>);
359 return std::make_unique<IndirectItem<ItemType>>(ptr);
370 template<
typename RegistryTraits,
typename Item>
372 const Placement &placement, std::unique_ptr<Item> pItem)
374 static_assert(AcceptableTraits_v<RegistryTraits>);
375 static_assert(AcceptableType_v<RegistryTraits, Item>,
376 "Registered item must be of one of the types listed in the registry's "
387 template<
typename RegistryClass>
390 template<
typename Ptr>
394 RegisterItem(RegistryClass::Registry(), placement, move(pItem));
400 template<
typename V>
auto ForwardTuple_(
const V &visitor, std::false_type) {
402 return std::tuple<const V&>{ visitor };
410 std::bool_constant<Tuple::is_tuple_like_v<V>>{});
413 template<
typename V>
auto MakeTuple_(
const V &visitor, std::false_type) {
415 return std::tuple<V>{ visitor };
417 template<
typename V>
auto MakeTuple_(
const V &visitor, std::true_type) {
423 std::bool_constant<Tuple::is_tuple_like_v<V>>{});
430 template<
typename V>
auto CaptureTuple_(
const V &visitor, std::false_type) {
434 template<
bool Reference,
typename V>
auto CaptureTuple(
const V &visitor) {
435 return CaptureTuple_(visitor, std::bool_constant<Reference>{});
439 template<
typename Types,
bool Reference,
typename Visitor>
441 return [visitor = CaptureTuple<Reference>(visitor)](
446 TypeSwitch::Dispatch<void, Types>(
object, visitor, path);
451 template<
typename Visitors>
static constexpr auto TupleSize =
453 Tuple::is_tuple_like_v<Visitors>,
454 std::tuple_size<Visitors>,
455 std::integral_constant<size_t, 1>
475 template<
typename RegistryTraits,
bool Reference = false>
477 detail::LeafVisitorFunction<RegistryTraits>,
478 detail::VisitorFunctionTriple<RegistryTraits>
492 decltype(
auto) forwarded = forward<Visitors>(visitors);
493 static constexpr auto size = TupleSize<std::decay_t<Visitors>>;
494 static_assert(
size == 1 ||
size == 3);
495 if constexpr (
size == 1)
496 this->
template emplace<0>(
497 MakeVisitorFunction<LeafTypes, Reference>(forwarded));
498 else if constexpr (
size == 3)
499 this->
template emplace<1>(
500 MakeVisitorFunction<NodeTypes, Reference>(get<0>(forwarded)),
501 MakeVisitorFunction<LeafTypes, Reference>(get<1>(forwarded)),
502 MakeVisitorFunction<NodeTypes, Reference>(get<2>(forwarded)));
507 if (
const auto *pTriple = std::get_if<1>(
this))
508 (std::get<0>(*pTriple))(item, path);
514 [](
const Function&
fn) ->
const Function & {
return fn; },
515 [](
auto &&self) ->
const Function & {
516 return std::get<1>(self); }
519 function(item, path);
524 if (
const auto *pTriple = std::get_if<1>(
this))
525 (std::get<2>(*pTriple))(item, path);
530 constexpr auto NoOp = [](
auto&,
auto&){};
545 REGISTRIES_API
void Visit(
549 void *pComputedItemContext);
555 template<
typename RegistryTraits,
typename Visitors>
560 static constexpr auto size = TupleSize<Visitors>;
561 static_assert(
size == 1 ||
size == 3);
566 if constexpr (
size == 3)
567 TypeSwitch::Dispatch<void, NodeTypes>(item,
571 TypeSwitch::Dispatch<void, LeafTypes>(item,
577 if constexpr (
size == 3)
578 TypeSwitch::Dispatch<void, NodeTypes>(item,
608 template<
typename RegistryTraits,
typename Visitors>
609 void Visit(
const Visitors &visitors,
612 typename RegistryTraits::ComputedItemContextType &computedItemContext =
613 RegistryTraits::ComputedItemContextType::Instance)
615 static_assert(AcceptableTraits_v<RegistryTraits>);
616 detail::Visitor<RegistryTraits, Visitors> visitor{ visitors };
617 detail::Visit(visitor, pTopItem, pRegistry, &computedItemContext);
622 template<
typename RegistryTraits>
626 typename RegistryTraits::ComputedItemContextType &computedItemContext =
627 RegistryTraits::ComputedItemContextType::Instance)
629 static_assert(AcceptableTraits_v<RegistryTraits>);
631 Visit(visitor, pTopItem, pRegistry, computedItemContext);
642 struct REGISTRIES_API
645 using Pair = std::pair< Literal, Literal >;
656 void operator () ()
override;
670 __declspec(dllexport)
Dispatch to one of a set of functions by the run-time type of an object.
emulates std::visit for one visitor
An explicitly nonlocalized string, not meant for the user to see.
Generates classes whose instances register items at construction.
RegisteredItem(Ptr pItem, const Placement &placement={})
virtual void EndGroup(const GroupItemBase &item, const Path &path) const =0
virtual void BeginGroup(const GroupItemBase &item, const Path &path) const =0
virtual void Visit(const SingleItem &item, const Path &path) const =0
VisitorFunction< Types > MakeVisitorFunction(const Visitor &visitor)
Capture a callable for Visit() in a std::function wrapper.
std::tuple< NodeVisitorFunction< RegistryTraits >, LeafVisitorFunction< RegistryTraits >, NodeVisitorFunction< RegistryTraits > > VisitorFunctionTriple
auto CaptureTuple_(const V &visitor, std::true_type)
std::shared_ptr< BaseItem > BaseItemSharedPtr
auto MakeTuple_(const V &visitor, std::false_type)
auto ForwardTuple_(const V &visitor, std::false_type)
auto CaptureTuple(const V &visitor)
REGISTRIES_API void Visit(VisitorBase &visitor, const GroupItemBase *pTopItem, const GroupItemBase *pRegistry, void *pComputedItemContext)
REGISTRIES_API void RegisterItem(GroupItemBase ®istry, const Placement &placement, BaseItemPtr pItem)
Type-erased implementation details, don't call directly.
std::unique_ptr< BaseItem > BaseItemPtr
VisitorFunction< VisitedLeafTypes< RegistryTraits > > LeafVisitorFunction
auto MakeTuple(const V &visitor)
std::function< void(Head_t< Types > &, const Path &)> VisitorFunction
static constexpr auto TupleSize
How large a tuple to make from Visitors.
auto ForwardTuple(const V &visitor)
typename ConsUnique< Type, List >::type ConsUnique_t
VisitorFunction< VisitedNodeTypes< RegistryTraits > > NodeVisitorFunction
ConsUnique_t< const GroupItem< RegistryTraits >, Map_t< Fn< std::add_const_t >, typename RegistryTraits::NodeTypes > > VisitedNodeTypes
ConsUnique_t< const SingleItem, Map_t< Fn< std::add_const_t >, typename RegistryTraits::LeafTypes > > VisitedLeafTypes
constexpr auto NoOp
Supply this when one member of a visitor function triple isn't needed.
std::vector< Identifier > Path
void Visit(const Visitors &visitors, const GroupItem< RegistryTraits > *pTopItem, const GroupItem< RegistryTraits > *pRegistry={}, typename RegistryTraits::ComputedItemContextType &computedItemContext=RegistryTraits::ComputedItemContextType::Instance)
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
typename ActualItem< T >::type ActualItem_t
void RegisterItem(GroupItem< RegistryTraits > ®istry, const Placement &placement, std::unique_ptr< Item > pItem)
typename AllTypes< RegistryTraits >::type AllTypes_t
constexpr auto AcceptableBaseItem_v
void VisitWithFunctions(const VisitorFunctions< RegistryTraits > &visitors, const GroupItem< RegistryTraits > *pTopItem, const GroupItem< RegistryTraits > *pRegistry={}, typename RegistryTraits::ComputedItemContextType &computedItemContext=RegistryTraits::ComputedItemContextType::Instance)
constexpr auto AcceptableType_v
constexpr auto AcceptableTraits_v
auto All(Tuple &&tuple)
Projection of all of a tuple.
auto ForwardAll(Tuple &&tuple)
Forwarding of all of a tuple.
Utilities for compile-time type manipulation. Some terminology as in Lisp.
typename Map< Metafunction, TypeList >::type Map_t
typename Cons< Type, TypeList >::type Cons_t
typename Head< TypeList >::type Head_t
typename Append< Lists... >::type Append_t
decltype(auto) Visit(Visitor &&vis, Variant &&var)
Mimic some of std::visit, for the case of one visitor only.
Builder(BaseArgs... args, Items &&... items)
Variadic constructor.
static constexpr auto ItemBuilder
static constexpr auto enables_item_type_v
static constexpr auto value
Find the real item type (following chains of indirections)
TypeList::Append_t< typename RegistryTraits::LeafTypes, typename RegistryTraits::NodeTypes > type
static EmptyContext Instance
Has variadic and range constructors that check types.
~GroupItem() override=default
enum Registry::OrderingHint::Type type
OrderingHint(Type type=Unspecified, const wxString &name={})
bool operator==(const OrderingHint &other) const
bool operator<(const OrderingHint &other) const
std::vector< Pair > Pairs
std::pair< Literal, Literal > Pair
Placement(const wxChar *path, const OrderingHint &hint={})
Placement(const wxString &path={}, const OrderingHint &hint={})
Common abstract base class for items that are not groups.
VisitorFunctions(Visitors &&visitors)
Type-erasing constructor.
detail::VisitedLeafTypes< RegistryTraits > LeafTypes
void BeginGroup(const GroupItem< RegistryTraits > &item, const Path &path) const
Call-through for a decorating pre-visitor.
void EndGroup(const GroupItem< RegistryTraits > &item, const Path &path) const
Call-through for a decorating post-visitor.
void Visit(const SingleItem &item, const Path &path) const
Call-through for a decorating leaf-visitor.
detail::VisitedNodeTypes< RegistryTraits > NodeTypes
OrderingHint orderingHint
BaseItem(const Identifier &internalName)
auto operator()(std::unique_ptr< ItemType > ptr) const
typename RegistryTraits::ComputedItemContextType Context
TypeErasedFactory factory
std::function< BaseItemSharedPtr(void *)> TypeErasedFactory
ComputedItemBase(const TypeErasedFactory &factory)
ComputedItem(const Factory &factory)
Type-erasing constructor template.
static constexpr bool value
std::conditional_t< std::disjunction< Null< List >, NotAlready< List > >::value, Cons_t< Type, List >, List > type
Common abstract base class for items that group other items.
friend REGISTRIES_API void RegisterItem(GroupItemBase ®istry, const Placement &placement, BaseItemPtr pItem)
Type-erased implementation details, don't call directly.
Ordering
Choose treatment of the children of the group when merging trees.
GroupItemBase(const GroupItemBase &)=delete
GroupItemBase & operator=(const GroupItemBase &)=delete
IndirectItemBase(const BaseItemSharedPtr &ptr)
An item that delegates to another held in a shared pointer.
IndirectItem(const std::shared_ptr< Item > &ptr)
Type-erasing adapter class (with no std::function overhead)
VisitedLeafTypes< RegistryTraits > LeafTypes
static constexpr auto size
ConsUnique_t< const GroupItemBase, VisitedNodeTypes< RegistryTraits > > NodeTypes
void BeginGroup(const GroupItemBase &item, const Path &path) const override
Visitor(const Visitors &visitors)
void Visit(const SingleItem &item, const Path &path) const override
const Visitors & visitors
void EndGroup(const GroupItemBase &item, const Path &path) const override
Whether the given type is derived from any member of the list.
Primary template for a list of arbitrary types.