Audacity 3.2.0
Composite.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 Composite.h
7 @brief Support for the Composite pattern
8
9 Paul Licameli
10
11 **********************************************************************/
12#ifndef __AUDACITY_COMPOSITE__
13#define __AUDACITY_COMPOSITE__
14
15#include <algorithm>
16#include <cassert>
17#include <iterator>
18#include <type_traits>
19#include <utility>
20#include <vector>
21
22namespace Composite {
23
27
33template<
34 typename Component,
35 typename ComponentPointer,
36 typename... ComponentArgs
37>
38class Base : public Component
39{
40public:
41 using value_type = ComponentPointer;
42 using Items = std::vector<value_type>;
43
44 explicit Base(ComponentArgs... args)
45 : Component{ std::forward<ComponentArgs>(args)... }
46 {
47 static_assert(std::has_virtual_destructor_v<Component>);
48 }
49
50 Base(const Base&) = delete;
51 Base& operator =(const Base&) = delete;
52
53 auto begin() const { return items.begin(); }
54 auto end() const { return items.end(); }
55 auto cbegin() const { return items.cbegin(); }
56 auto cend() const { return items.cend(); }
57 auto rbegin() const { return items.rbegin(); }
58 auto rend() const { return items.rend(); }
59 auto crbegin() const { return items.crbegin(); }
60 auto crend() const { return items.crend(); }
61
62 void push_back(value_type ptr){ items.push_back(move(ptr)); }
63 auto size() const noexcept { return items.size(); }
64
65 [[nodiscard]] bool empty() const { return items.empty(); }
66
67protected:
69};
70
73
79template<typename Base, typename Derived> struct Traits {
80 static constexpr auto ItemBuilder = std::move<typename Base::value_type>;
81 template<typename T> static constexpr auto enables_item_type_v = true;
82};
83
84namespace detail {
85template<bool Deprecate> struct This;
86template<> struct This<false> {};
87template<> struct [[deprecated(
88 "Composite::Builder specialization does not enable Base::value_type"
89)]] This<true> {};
90}
91
95
98template<typename Base, typename Derived, typename... BaseArgs>
99struct Builder : Base
100{
101 using BaseType = Base;
102
105 template<typename Arg> auto push_back(Arg &&arg)
106 -> std::enable_if_t<Traits<Base, Derived>
107 ::template enables_item_type_v<Arg>,
108 void
109 >
110 {
111 static constexpr auto ItemBuilder = Traits<Base, Derived>::ItemBuilder;
112 Base::push_back(ItemBuilder(std::forward<Arg>(arg)));
113 }
116 void push_back(typename Base::value_type arg) {
117 constexpr auto enable = Traits<Base, Derived>
118 ::template enables_item_type_v<typename Base::value_type>;
119 // We can't sfinae this overload away when traits want to disable it, but
120 // we can make a deprecation
121 static const detail::This<!enable> deprecator;
122 if constexpr(!enable) {
123 assert(false);
124 }
125 else {
126 static constexpr auto ItemBuilder = Traits<Base, Derived>::ItemBuilder;
127 Base::push_back(ItemBuilder(move(arg)));
128 }
129 }
130
132 template<typename... Items>
133 Builder(BaseArgs... args, Items&&... items)
134 : Base{ std::forward<BaseArgs>(args)... }
135 {
136 (..., push_back(std::forward<Items>(items)));
137 }
138
140 template<typename InputIterator,
141 typename Arg = decltype(*std::declval<InputIterator>()),
142 typename ItemBuilder = decltype(Traits<Base, Derived>::ItemBuilder),
143 typename sfinae = std::enable_if_t<std::is_invocable_v<ItemBuilder, Arg>>>
144 Builder(BaseArgs... args, InputIterator begin, InputIterator end)
145 : Builder{
146 std::forward<BaseArgs>(args)..., begin, end,
147 [](Arg &&arg) -> decltype(auto) { return std::forward<Arg>(arg); }
148 }
149 {}
150
152 template<typename InputIterator, typename Transformer,
153 typename Arg = decltype(*std::declval<InputIterator>()),
154 typename ItemBuilder = decltype(Traits<Base, Derived>::ItemBuilder),
155 typename sfinae = std::enable_if_t<std::is_invocable_v<
156 ItemBuilder, std::invoke_result_t<Transformer, Arg>>>>
157 Builder(BaseArgs... args,
158 InputIterator begin, InputIterator end, Transformer transformer
159 ) : Base{ std::forward<BaseArgs>(args)... } {
160 std::for_each(begin, end,
161 [this, &transformer](Arg &&arg){ push_back(transformer(arg)); });
162 }
163
164private:
165 using BaseType::push_back;
166};
167
169template<
170 typename Base,
171 typename Base2,
172 typename... RequiredBaseArgs
173>
175 : public Base
176 , protected Base2
177{
178 template<typename... OtherBaseArgs>
179 Extension(RequiredBaseArgs... args, Base2 arg2,
180 OtherBaseArgs &&...otherArgs
181 ) : Base{ std::forward<RequiredBaseArgs>(args)...,
182 std::forward<OtherBaseArgs>(otherArgs)...
183 }
184 , Base2{ std::move(arg2) }
185 {}
186};
187
189template<
190 typename Base,
191 typename... RequiredBaseArgs
192> struct Extension<
193 Base,
194 void,
195 RequiredBaseArgs...
196>
197 : public Base
198{
199 template<typename... OtherBaseArgs>
200 Extension(RequiredBaseArgs... args, OtherBaseArgs &&...otherArgs)
201 : Base{ std::forward<RequiredBaseArgs>(args)...,
202 std::forward<OtherBaseArgs>(otherArgs)...
203 }
204 {}
205};
206
207}
208
209#endif
bool empty() const
Definition: Composite.h:65
Base(ComponentArgs... args)
Definition: Composite.h:44
auto rend() const
Definition: Composite.h:58
auto cend() const
Definition: Composite.h:56
auto cbegin() const
Definition: Composite.h:55
ComponentPointer value_type
Definition: Composite.h:41
auto crbegin() const
Definition: Composite.h:59
Base & operator=(const Base &)=delete
void push_back(value_type ptr)
Definition: Composite.h:62
auto crend() const
Definition: Composite.h:60
auto begin() const
Definition: Composite.h:53
std::vector< value_type > Items
Definition: Composite.h:42
auto rbegin() const
Definition: Composite.h:57
Base(const Base &)=delete
auto end() const
Definition: Composite.h:54
auto size() const noexcept
Definition: Composite.h:63
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
STL namespace.
Builder(BaseArgs... args, InputIterator begin, InputIterator end, Transformer transformer)
Iterator range constructor, with explicit transformer.
Definition: Composite.h:157
Builder(BaseArgs... args, Items &&... items)
Variadic constructor.
Definition: Composite.h:133
Builder(BaseArgs... args, InputIterator begin, InputIterator end)
Iterator range constructor, with default transformer.
Definition: Composite.h:144
void push_back(typename Base::value_type arg)
Definition: Composite.h:116
auto push_back(Arg &&arg) -> std::enable_if_t< Traits< Base, Derived > ::template enables_item_type_v< Arg >, void >
Definition: Composite.h:105
Extension(RequiredBaseArgs... args, OtherBaseArgs &&...otherArgs)
Definition: Composite.h:200
Extend Base with extra fields, in a second, protected base class.
Definition: Composite.h:177
Extension(RequiredBaseArgs... args, Base2 arg2, OtherBaseArgs &&...otherArgs)
Definition: Composite.h:179
static constexpr auto ItemBuilder
Definition: Composite.h:80
static constexpr auto enables_item_type_v
Definition: Composite.h:81