Audacity 3.2.0
TypeEnumerator.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*!********************************************************************
3
4 Audacity: A Digital Audio Editor
5
6 @file TypeEnumerator.h
7
8 @brief Make a list of all distinct types so far mentioned in calls of a
9 certain macro
10
11 Paul Licameli
12
13**********************************************************************/
14#ifndef __AUDACITY_TYPE_ENUMERATOR__
15#define __AUDACITY_TYPE_ENUMERATOR__
16
17#include "TypeList.h"
18
19namespace TypeEnumerator {
20
21namespace detail {
22
24template<typename T> struct type_identity{ using type = T; };
25
27struct Unenumerated : type_identity<Unenumerated> {};
28
31template<typename Tag, typename Location, unsigned U> using EnumeratedType =
32 typename decltype(enumerateTypes(
33 Tag{}, Location{}, std::integral_constant<unsigned, U>{}))::type;
34
37
42template<typename Tag, typename Location> class CountTypes {
43 template<unsigned U> struct Stop{ static constexpr unsigned value = U; };
44 template<unsigned U> struct Count : std::conditional_t<
45 std::is_same_v<Unenumerated, EnumeratedType<Tag, Location, U>>,
46 Stop<U>,
47 Count<U + 1>
48 > {};
49public:
50 static constexpr unsigned value = Count<0>::value;
51};
52
54template<typename Tag, typename T>
56 // Generate a type for the location of the macro call
57 struct Location : Tag {};
58 // Count types for this new location, stopping one later than for the
59 // last specialization
60 static constexpr unsigned value = CountTypes<Tag, Location>::value;
61 // value is then used to make a new association for the next TypeCounter
62 // with a previously unseen T
63};
64
65}
66
74#define BEGIN_TYPE_ENUMERATION(Tag) namespace { \
75 struct Tag{}; \
76 auto enumerateTypes(Tag, Tag, ...) -> TypeEnumerator::detail::Unenumerated; }
77
79#define ENUMERATE_TYPE(Tag, T) namespace { auto enumerateTypes( \
80 Tag, Tag, std::integral_constant<unsigned, \
81 TypeEnumerator::detail::TypeCounter<Tag, T>::value>) \
82 -> TypeEnumerator::detail::type_identity<T>; }
83
86
90template<typename Tag, typename Location> class CollectTypes {
91 static_assert(std::is_base_of_v<Tag, Location>);
92 template<typename... Types> struct Stop{
93 using type = TypeList::List<Types...>; };
94 // This works by mutual recursion of Accumulate and AccumulateType
95 template<unsigned U, typename... Types> struct Accumulate;
96 template<unsigned U, typename Type, typename... Types> struct AccumulateType
97 : std::conditional_t<std::is_same_v<detail::Unenumerated, Type>,
98 Stop<Types...>,
99 Accumulate<U + 1, Types..., Type>
100 >
101 {};
102 template<unsigned U, typename... Types> struct Accumulate
103 : AccumulateType<U, detail::EnumeratedType<Tag, Location, U>, Types...>
104 {};
105public:
106 using type = typename Accumulate<0>::type;
107};
108
109}
110
111#endif
Metaprogramming utilities for manipulating lists of types.
typename Accumulate< 0 >::type type
static constexpr unsigned value
Used only by WaveTrack, a special way to hold location that can accommodate merged regions.
typename decltype(enumerateTypes(Tag{}, Location{}, std::integral_constant< unsigned, U >{}))::type EnumeratedType
Implements the ENUMERATE_TYPE macro.
static constexpr unsigned value
A type excluded from any enumeration.
Primary template for a list of arbitrary types.
Definition: TypeList.h:61