30#ifndef APF_CONTAINER_H
31#define APF_CONTAINER_H
47 template<
typename T1,
typename...>
struct first {
using type = T1; };
52 template<
typename T1,
typename... Ts>
struct last : last<Ts...> {};
53 template<
typename T1>
struct last<T1> {
using type = T1; };
55 template<
typename... Args>
using if_first_not_integral
56 =
typename std::enable_if<
57 !std::is_integral<
typename first<Args...>::type>::value>::type;
58 template<
typename X>
using if_integral
59 =
typename std::enable_if<std::is_integral<X>::value>::type;
61 template<
typename Arg,
typename... Args>
using if_last_not_convertible
62 =
typename std::enable_if<
63 !std::is_convertible<
typename last<Args...>::type, Arg>::value>::type;
81template<
typename T,
typename Allocator = std::allocator<T>>
85 using _base =
typename std::vector<T, Allocator>;
88 using typename _base::value_type;
89 using typename _base::allocator_type;
90 using typename _base::reference;
91 using typename _base::const_reference;
92 using typename _base::pointer;
93 using typename _base::const_pointer;
94 using typename _base::iterator;
95 using typename _base::const_iterator;
96 using typename _base::reverse_iterator;
97 using typename _base::const_reverse_iterator;
98 using typename _base::difference_type;
99 using typename _base::size_type;
108 template<
typename... Args,
typename =
109 internal::if_first_not_integral<Args...>>
111 : _base(std::forward<Args>(args)...)
117 template<
typename Size,
typename =
internal::if_
integral<Size>>
122 explicit fixed_vector(size_type n) : _base(n) {}
125 template<
typename Size,
typename Arg
126 ,
typename = internal::if_integral<Size>>
127 fixed_vector(Size n, Arg&& arg,
const Allocator& a)
128 : _base(static_cast<size_type>(n), std::forward<Arg>(arg), a)
133 template<
typename Size,
typename... Args
134 ,
typename = internal::if_integral<Size>
135 ,
typename = internal::if_last_not_convertible<Allocator, Args...>>
139 _base::reserve(
static_cast<size_type
>(n));
140 for (Size i = 0; i < n; ++i)
143 _base::emplace_back(args...);
148 explicit fixed_vector(std::initializer_list<value_type> il
149 ,
const Allocator& a = Allocator())
161 if (this->capacity() == 0)
167 throw std::logic_error(
168 "Bug: fixed_vector::resize() is only allowed if capacity == 0!");
180 if (this->capacity() == 0)
186 throw std::logic_error(
187 "Bug: fixed_vector::reserve() is only allowed if capacity == 0!");
198 template<
typename... Args>
201 if (this->size() < this->capacity())
203 _base::emplace_back(std::forward<Args>(args)...);
207 throw std::logic_error(
208 "Bug: fixed_vector::emplace_back() "
209 "is only allowed if size < capacity!");
221 using _base::crbegin;
224 using _base::max_size;
225 using _base::capacity;
227 using _base::operator[];
230 using _base::get_allocator;
238template<
typename T,
typename Allocator = std::allocator<T>>
242 using _base =
typename std::list<T, Allocator>;
245 using typename _base::value_type;
246 using typename _base::allocator_type;
247 using typename _base::reference;
248 using typename _base::const_reference;
249 using typename _base::pointer;
250 using typename _base::const_pointer;
251 using typename _base::iterator;
252 using typename _base::const_iterator;
253 using typename _base::reverse_iterator;
254 using typename _base::const_reverse_iterator;
255 using typename _base::difference_type;
256 using typename _base::size_type;
265 template<
typename... Args,
typename =
266 internal::if_first_not_integral<Args...>>
268 : _base(std::forward<Args>(args)...)
272 template<
typename Size,
typename... Args,
typename =
273 internal::if_integral<Size>>
277 for (Size i = 0; i < n; ++i)
280 _base::emplace_back(args...);
284 explicit fixed_list(std::initializer_list<value_type> il
285 ,
const Allocator& a = Allocator())
292 void move(iterator from, iterator to)
294 _base::splice(to, *
this, from);
300 void move(iterator first, iterator last, iterator target)
302 _base::splice(target, *
this, first, last);
311 using _base::crbegin;
315 using _base::max_size;
318 using _base::get_allocator;
319 using _base::reverse;
340template<
typename T,
typename Allocator = std::allocator<T>>
347 using typename _base::pointer;
348 using typename _base::size_type;
382 ,
const Allocator& a = Allocator())
391 void initialize(size_type max_channels, size_type max_slices)
395 this->
channels = make_begin_and_end(
397 this->
slices = make_begin_and_end(
400 _channel_ptrs.
reserve(max_channels);
401 for (
const auto channel: this->
channels)
405 assert(_channel_ptrs.size() == max_channels);
408 template<
typename Ch>
430template<
typename T,
typename Allocator>
438 struct ChannelArrowProxy :
Channel
441 Channel* operator->() {
return this; }
445 using iterator_category = std::random_access_iterator_tag;
449 using pointer = ChannelArrowProxy;
460 : _base_iterator(base_iterator, static_cast<difference_type>(step))
468 auto temp = _base_iterator.base();
470 return Channel(temp, temp + _size);
477 return this->operator*();
496 _base_type _base_iterator;
501template<
typename T,
typename Allocator>
508 struct SliceArrowProxy :
Slice
510 SliceArrowProxy(
const Slice& sl) :
Slice(sl) {}
511 Slice* operator->() {
return this; }
515 using iterator_category = std::random_access_iterator_tag;
518 using pointer = SliceArrowProxy;
519 using difference_type
520 =
typename std::iterator_traits<channel_iterator>::difference_type;
532 , size_type max_channels, size_type max_slices)
533 : _base_iterator(base_iterator)
534 , _max_channels(max_channels)
535 , _max_slices(max_slices)
544 ,
static_cast<difference_type
>(_max_slices)};
545 return Slice(temp, temp +
static_cast<difference_type
>(_max_channels));
552 return this->operator*();
572 size_type _max_channels;
573 size_type _max_slices;
586template<
typename T,
typename Allocator>
591 assert(std::distance(ch.begin(), ch.end())
592 == std::distance(this->channels.begin(), this->channels.end()));
593 assert((ch.begin() == ch.end()) ?
true :
594 std::distance(ch.begin()->begin(), ch.begin()->end()) ==
595 std::distance(this->channels.begin()->begin()
596 , this->channels.begin()->end()));
598 auto target = this->channels.begin();
600 for (
const auto i: ch)
602 std::copy(i.begin(), i.end(), target->begin());
609template<
typename L1,
typename L2>
612 for (
auto& i: source)
614 target.push_back(&i);
620template<
typename L1,
typename L2>
623 for (
const auto& i: source)
625 target.push_back(&i);
638template<
typename L1,
typename L2,
typename DataMember>
641 if (source.size() != target.size())
643 throw std::logic_error(
"distribute_list: Different sizes!");
646 auto in = source.begin();
648 for (
auto& out: target)
650 (out.*member).splice((out.*member).end(), source, in++);
667template<
typename L1,
typename L2,
typename DataMember,
typename L3>
671 if (source.size() != target.size())
673 throw std::logic_error(
"undistribute_list(): Different sizes!");
676 auto in = source.begin();
678 for (
auto& out: target)
681 = std::find((out.*member).begin(), (out.*member).end(), *in++);
682 if (delinquent == (out.*member).end())
684 throw std::logic_error(
"undistribute_list(): Element not found!");
686 garbage.splice(garbage.end(), out.*member, delinquent);
Derived from std::list, but without re-sizing.
void move(iterator first, iterator last, iterator target)
Move range (from first to last) to target.
fixed_list(Size n, Args &&... args)
Constructor from size and initialization arguments.
void move(iterator from, iterator to)
Move list element from one place to another.
fixed_list(Args &&... args)
Constructor that forwards everything except if first type is integral.
Iterator over fixed_matrix::Channels.
channels_iterator()
Default constructor.
channels_iterator(channel_iterator base_iterator, size_type step)
Constructor.
reference operator*() const
Dereference operator.
pointer operator->() const
Arrow operator.
Iterator over fixed_matrix::Slices.
slices_iterator(channel_iterator base_iterator, size_type max_channels, size_type max_slices)
Constructor.
slices_iterator()
Default constructor.
reference operator*() const
Dereference operator.
pointer operator->() const
Arrow operator.
Two-dimensional data storage for row- and column-wise access.
fixed_matrix(size_type max_channels, size_type max_slices, const Allocator &a=Allocator())
Constructor.
has_begin_and_end< slices_iterator > slices
Access to Slices; use slices.begin() and slices.end()
has_begin_and_end< stride_iterator< channel_iterator > > Slice
Proxy class for returning one slice of the fixed_matrix.
pointer const * get_channel_ptrs() const
Get array of pointers to the channels.
void initialize(size_type max_channels, size_type max_slices)
Allocate memory for max_channels x max_slices elements and default-construct them.
typename Channel::iterator channel_iterator
Iterator within a Channel.
has_begin_and_end< channels_iterator > channels
Access to Channels; use channels.begin() and channels.end()
void set_channels(const Ch &ch)
Copy channels from another matrix.
typename Slice::iterator slice_iterator
Iterator within a Slice.
has_begin_and_end< pointer > Channel
Proxy class for returning one channel of the fixed_matrix.
fixed_matrix(const Allocator &a=Allocator())
Default constructor.
Derived from std::vector, but without memory re-allocations.
void reserve(size_type n)
Reserve space for new elements.
void emplace_back(Args &&... args)
Construct element at the end.
fixed_vector(Args &&... args)
Constructor that forwards everything except if first type is integral.
void resize(size_type n)
Reserve space for new elements and default-construct them.
fixed_vector(Size n, Args &&... args)
Constructor from size and initialization arguments.
Convenience class providing begin() and end().
typename std::iterator_traits< channel_iterator >::difference_type difference_type
#define APF_ITERATOR_RANDOMACCESS_POSTINCREMENT
Postincrement operator (using preincrement operator).
#define APF_ITERATOR_RANDOMACCESS_SUBSCRIPT
Straightforward subscript operator (using + and dereference operator).
#define APF_ITERATOR_RANDOMACCESS_ADDITION_ASSIGNMENT(base_member)
Straightforward addition/assignment operator.
#define APF_ITERATOR_RANDOMACCESS_THE_REST
The rest of the random access iterator requirements.
#define APF_ITERATOR_RANDOMACCESS_PREDECREMENT
Straightforward predecrement operator.
#define APF_ITERATOR_RANDOMACCESS_LESS(base_member)
Straightforward less-than operator.
#define APF_ITERATOR_RANDOMACCESS_PREINCREMENT
Straightforward preincrement operator.
#define APF_ITERATOR_RANDOMACCESS_UNEQUAL
Unequality operator (using equality operator).
#define APF_ITERATOR_RANDOMACCESS_EQUAL
Straightforward equality operator.
#define APF_ITERATOR_RANDOMACCESS_POSTDECREMENT
Postdecrement operator (using predecrement operator)
#define APF_ITERATOR_BASE(base_iterator_type, base_member)
Get the base iterator.
#define APF_ITERATOR_RANDOMACCESS_OTHER_COMPARISONS
Other comparisons (>, <=, >=).
#define APF_ITERATOR_RANDOMACCESS_DIFFERENCE(base_member)
Straightforward difference operator.
Several more or less useful iterators and some macros.
Audio Processing Framework.
void distribute_list(L1 &source, L2 &target, DataMember member)
Splice list elements from source to member lists of target.
void undistribute_list(const L1 &source, L2 &target, DataMember member, L3 &garbage)
The opposite of distribute_list() – sorry for the strange name!
bool no_nullptr(T *in)
Check for null-pointer.
void append_pointers(L1 &source, L2 &target)
Append pointers to the elements of the first list to the second list.