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
64 [[nodiscard]] bool empty() const { return items.empty(); }
65
66protected:
68};
69
72
78template<typename Base, typename Derived> struct Traits {
79 static constexpr auto ItemBuilder = std::move<typename Base::value_type>;
80 template<typename T> static constexpr auto enables_item_type_v = true;
81};
82
83namespace detail {
84template<bool Deprecate> struct This;
85template<> struct This<false> {};
86template<> struct [[deprecated(
87 "Composite::Builder specialization does not enable Base::value_type"
88)]] This<true> {};
89}
90
94
97template<typename Base, typename Derived, typename... BaseArgs>
98struct Builder : Base
99{
100 using BaseType = Base;
101
104 template<typename Arg> auto push_back(Arg &&arg)
105 -> std::enable_if_t<Traits<Base, Derived>
106 ::template enables_item_type_v<Arg>,
107 void
108 >
109 {
110 static constexpr auto ItemBuilder = Traits<Base, Derived>::ItemBuilder;
111 Base::push_back(ItemBuilder(std::forward<Arg>(arg)));
112 }
115 void push_back(typename Base::value_type arg) {
116 constexpr auto enable = Traits<Base, Derived>
117 ::template enables_item_type_v<typename Base::value_type>;
118 // We can't sfinae this overload away when traits want to disable it, but
119 // we can make a deprecation
120 static const detail::This<!enable> deprecator;
121 if constexpr(!enable) {
122 assert(false);
123 }
124 else {
125 static constexpr auto ItemBuilder = Traits<Base, Derived>::ItemBuilder;
126 Base::push_back(ItemBuilder(move(arg)));
127 }
128 }
129
131 template<typename... Items>
132 Builder(BaseArgs... args, Items&&... items)
133 : Base{ std::forward<BaseArgs>(args)... }
134 {
135 (..., push_back(std::forward<Items>(items)));
136 }
137
139 template<typename InputIterator,
140 typename Arg = decltype(*std::declval<InputIterator>()),
141 typename ItemBuilder = decltype(Traits<Base, Derived>::ItemBuilder),
142 typename sfinae = std::enable_if_t<std::is_invocable_v<ItemBuilder, Arg>>>
143 Builder(BaseArgs... args, InputIterator begin, InputIterator end)
144 : Builder{
145 std::forward<BaseArgs>(args)..., begin, end,
146 [](Arg &&arg) -> decltype(auto) { return std::forward<Arg>(arg); }
147 }
148 {}
149
151 template<typename InputIterator, typename Transformer,
152 typename Arg = decltype(*std::declval<InputIterator>()),
153 typename ItemBuilder = decltype(Traits<Base, Derived>::ItemBuilder),
154 typename sfinae = std::enable_if_t<std::is_invocable_v<
155 ItemBuilder, std::invoke_result_t<Transformer, Arg>>>>
156 Builder(BaseArgs... args,
157 InputIterator begin, InputIterator end, Transformer transformer
158 ) : Base{ std::forward<BaseArgs>(args)... } {
159 std::for_each(begin, end,
160 [this, &transformer](Arg &&arg){ push_back(transformer(arg)); });
161 }
162
163private:
164 using BaseType::push_back;
165};
166
168template<
169 typename Base,
170 typename Base2,
171 typename... RequiredBaseArgs
172>
174 : public Base
175 , protected Base2
176{
177 template<typename... OtherBaseArgs>
178 Extension(RequiredBaseArgs... args, Base2 arg2,
179 OtherBaseArgs &&...otherArgs
180 ) : Base{ std::forward<RequiredBaseArgs>(args)...,
181 std::forward<OtherBaseArgs>(otherArgs)...
182 }
183 , Base2{ std::move(arg2) }
184 {}
185};
186
188template<
189 typename Base,
190 typename... RequiredBaseArgs
191> struct Extension<
192 Base,
193 void,
194 RequiredBaseArgs...
195>
196 : public Base
197{
198 template<typename... OtherBaseArgs>
199 Extension(RequiredBaseArgs... args, OtherBaseArgs &&...otherArgs)
200 : Base{ std::forward<RequiredBaseArgs>(args)...,
201 std::forward<OtherBaseArgs>(otherArgs)...
202 }
203 {}
204};
205
206}
207
208#endif
bool empty() const
Definition: Composite.h:64
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 end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
STL namespace.
Builder(BaseArgs... args, InputIterator begin, InputIterator end, Transformer transformer)
Iterator range constructor, with explicit transformer.
Definition: Composite.h:156
Builder(BaseArgs... args, Items &&... items)
Variadic constructor.
Definition: Composite.h:132
Builder(BaseArgs... args, InputIterator begin, InputIterator end)
Iterator range constructor, with default transformer.
Definition: Composite.h:143
void push_back(typename Base::value_type arg)
Definition: Composite.h:115
auto push_back(Arg &&arg) -> std::enable_if_t< Traits< Base, Derived > ::template enables_item_type_v< Arg >, void >
Definition: Composite.h:104
Extension(RequiredBaseArgs... args, OtherBaseArgs &&...otherArgs)
Definition: Composite.h:199
Extend Base with extra fields, in a second, protected base class.
Definition: Composite.h:176
Extension(RequiredBaseArgs... args, Base2 arg2, OtherBaseArgs &&...otherArgs)
Definition: Composite.h:178
static constexpr auto ItemBuilder
Definition: Composite.h:79
static constexpr auto enables_item_type_v
Definition: Composite.h:80