Audacity  2.3.1
MemoryX.h
Go to the documentation of this file.
1 #ifndef __AUDACITY_MEMORY_X_H__
2 #define __AUDACITY_MEMORY_X_H__
3 
4 // C++ standard header <memory> with a few extensions
5 #include <memory>
6 #include <cstdlib> // Needed for free.
7 #ifndef safenew
8 #define safenew new
9 #endif
10 
11 
12 #include <functional>
13 
14 #if !(_MSC_VER >= 1800 || __cplusplus >= 201402L)
15 /* replicate the very useful C++14 make_unique for those build environments
16 that don't implement it yet.
17 typical useage:
18 auto p = std::make_unique<Myclass>(ctorArg1, ctorArg2, ... ctorArgN);
19 p->DoSomething();
20 auto q = std::make_unique<Myclass[]>(count);
21 q[0].DoSomethingElse();
22 
23 The first hides naked NEW and DELETE from the source code.
24 The second hides NEW[] and DELETE[]. Both of course ensure destruction if
25 you don't use something like std::move(p) or q.release(). Both expressions require
26 that you identify the type only once, which is brief and less error prone.
27 
28 (Whereas this omission of [] might invite a runtime error:
29 std::unique_ptr<Myclass> q { safenew Myclass[count] }; )
30 
31 Some C++11 tricks needed here are (1) variadic argument lists and
32 (2) making the compile-time dispatch work correctly. You can't have
33 a partially specialized template function, but you get the effect of that
34 by other metaprogramming means.
35 */
36 
37 namespace std {
38  // For overloading resolution
39  template <typename X> struct __make_unique_result {
40  using scalar_case = unique_ptr<X>;
41  };
42 
43  // Partial specialization of the struct for array case
44  template <typename X> struct __make_unique_result<X[]> {
45  using array_case = unique_ptr<X[]>;
46  using element = X;
47  };
48 
49  // Now the scalar version of unique_ptr
50  template<typename X, typename... Args> inline
52  make_unique(Args&&... args)
53  {
55  { safenew X(forward<Args>(args)...) };
56  }
57 
58  // Now the array version of unique_ptr
59  // The compile-time dispatch trick is that the non-existence
60  // of the scalar_case type makes the above overload
61  // unavailable when the template parameter is explicit
62  template<typename X> inline
63  typename __make_unique_result<X>::array_case
64  make_unique(size_t count)
65  {
66  return typename __make_unique_result<X>::array_case
67  { safenew typename __make_unique_result<X>::element[count] };
68  }
69 }
70 #endif
71 
72 /*
73  * ArrayOf<X>
74  * Not to be confused with std::array (which takes a fixed size) or std::vector
75  * This maintains a pointer allocated by NEW X[]. It's cheap: only one pointer,
76  * with no size and capacity information for resizing as for vector, and if X is
77  * a built-in numeric or pointer type, by default there is no zero filling at
78  * allocation time.
79  */
80 
81 template<typename X>
82 class ArrayOf : public std::unique_ptr<X[]>
83 {
84 public:
85  ArrayOf() {}
86 
87  template<typename Integral>
88  explicit ArrayOf(Integral count, bool initialize = false)
89  {
90  static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
91  reinit(count, initialize);
92  }
93 
94  //ArrayOf(const ArrayOf&) PROHIBITED;
95  ArrayOf(const ArrayOf&) = delete;
96  ArrayOf(ArrayOf&& that)
97  : std::unique_ptr < X[] >
98  (std::move((std::unique_ptr < X[] >&)(that)))
99  {
100  }
102  {
103  std::unique_ptr<X[]>::operator=(std::move(that));
104  return *this;
105  }
106  ArrayOf& operator= (std::unique_ptr<X[]> &&that)
107  {
108  std::unique_ptr<X[]>::operator=(std::move(that));
109  return *this;
110  }
111 
112  template< typename Integral >
113  void reinit(Integral count,
114  bool initialize = false)
115  {
116  static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
117  if (initialize)
118  // Initialize elements (usually, to zero for a numerical type)
119  std::unique_ptr<X[]>::reset(safenew X[count]{});
120  else
121  // Avoid the slight initialization overhead
122  std::unique_ptr<X[]>::reset(safenew X[count]);
123  }
124 };
125 
135 template<typename X>
136 class ArraysOf : public ArrayOf<ArrayOf<X>>
137 {
138 public:
139  ArraysOf() {}
140 
141  template<typename Integral>
142  explicit ArraysOf(Integral N)
143  : ArrayOf<ArrayOf<X>>( N )
144  {}
145 
146  template<typename Integral1, typename Integral2 >
147  ArraysOf(Integral1 N, Integral2 M, bool initialize = false)
148  : ArrayOf<ArrayOf<X>>( N )
149  {
150  static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
151  static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
152  for (size_t ii = 0; ii < N; ++ii)
153  (*this)[ii] = ArrayOf<X>{ M, initialize };
154  }
155 
156  //ArraysOf(const ArraysOf&) PROHIBITED;
157  ArraysOf(const ArraysOf&) =delete;
159  {
160  ArrayOf<ArrayOf<X>>::operator=(std::move(that));
161  return *this;
162  }
163 
164  template< typename Integral >
165  void reinit(Integral count)
166  {
167  ArrayOf<ArrayOf<X>>::reinit( count );
168  }
169 
170  template< typename Integral >
171  void reinit(Integral count, bool initialize)
172  {
173  ArrayOf<ArrayOf<X>>::reinit( count, initialize );
174  }
175 
176  template<typename Integral1, typename Integral2 >
177  void reinit(Integral1 countN, Integral2 countM, bool initialize = false)
178  {
179  static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
180  static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
181  reinit(countN, false);
182  for (size_t ii = 0; ii < countN; ++ii)
183  (*this)[ii].reinit(countM, initialize);
184  }
185 };
186 
200 // Placement-NEW is used below, and that does not cooperate with the DEBUG_NEW for Visual Studio
201 #ifdef _DEBUG
202 #ifdef _MSC_VER
203 #undef new
204 #endif
205 #endif
206 
207 
208 template<typename X>
209 class Maybe {
210 public:
211 
212  // Construct as NULL
213  Maybe() {}
214 
215  // Supply the copy and move, so you might use this as a class member too
216  Maybe(const Maybe &that)
217  {
218  if (that.get())
219  create(*that);
220  }
221 
222  Maybe& operator= (const Maybe &that)
223  {
224  if (this != &that) {
225  if (that.get())
226  create(*that);
227  else
228  reset();
229  }
230  return *this;
231  }
232 
233  Maybe(Maybe &&that)
234  {
235  if (that.get())
236  create(::std::move(*that));
237  }
238 
240  {
241  if (this != &that) {
242  if (that.get())
243  create(::std::move(*that));
244  else
245  reset();
246  }
247  return *this;
248  }
249 
255  template<typename... Args>
256  void create(Args&&... args)
257  {
258  // Lose any old value
259  reset();
260  // Create NEW value
261  pp = safenew(address()) X(std::forward<Args>(args)...);
262  }
263 
264  // Destroy any object that was built in it
266  {
267  reset();
268  }
269 
270  // Pointer-like operators
271 
273  X &operator* () const
274  {
275  return *pp;
276  }
277 
278  X *operator-> () const
279  {
280  return pp;
281  }
282 
283  X* get() const
284  {
285  return pp;
286  }
287 
288  void reset()
289  {
290  if (pp)
291  pp->~X(), pp = nullptr;
292  }
293 
294  // So you can say if(ptr)
295  explicit operator bool() const
296  {
297  return pp != nullptr;
298  }
299 
300 private:
301  X* address()
302  {
303  return reinterpret_cast<X*>(&storage);
304  }
305 
306  // Data
307 #if 0
308  typename ::std::aligned_storage<
309  sizeof(X)
310  // , alignof(X) // Not here yet in all compilers
311  >::type storage{};
312 #else
313  union {
314  double d;
315  char storage[sizeof(X)];
316  };
317 #endif
318  X* pp{ nullptr };
319 };
320 
321 // Restore definition of debug new
322 #ifdef _DEBUG
323 #ifdef _MSC_VER
324 #undef THIS_FILE
325 static char*THIS_FILE = __FILE__;
326 #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__)
327 #endif
328 #endif
329 
333 struct freer { void operator() (void *p) const { free(p); } };
334 
338 template< typename T >
339 using MallocPtr = std::unique_ptr< T, freer >;
340 
344 template <typename Character = char>
345 using MallocString = std::unique_ptr< Character[], freer >;
346 
352 template <typename T>
353 struct Destroyer {
354  void operator () (T *p) const { if (p) p->Destroy(); }
355 };
356 
360 template <typename T>
361 using Destroy_ptr = std::unique_ptr<T, Destroyer<T>>;
362 
370 // Construct this from any copyable function object, such as a lambda
371 template <typename F>
372 struct Final_action {
373  Final_action(F f) : clean( f ) {}
375  F clean;
376 };
377 
380 template <typename F>
381 Final_action<F> finally (F f)
382 {
383  return Final_action<F>(f);
384 }
385 
386 #include <wx/utils.h> // for wxMin, wxMax
387 #include <algorithm>
388 
392 template< typename T >
393 struct RestoreValue {
395  void operator () ( T *p ) const { if (p) *p = oldValue; }
396 };
397 
398 
402 template< typename T >
403 class ValueRestorer : public std::unique_ptr< T, RestoreValue<T> >
404 {
405  using std::unique_ptr< T, RestoreValue<T> >::reset; // make private
406  // But release() remains public and can be useful to commit a changed value
407 public:
408  explicit ValueRestorer( T &var )
409  : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
410  {}
411  explicit ValueRestorer( T &var, const T& newValue )
412  : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
413  { var = newValue; }
415  : std::unique_ptr < T, RestoreValue<T> > ( std::move(that) ) {};
417  {
418  if (this != &that)
419  std::unique_ptr < T, RestoreValue<T> >::operator=(std::move(that));
420  return *this;
421  }
422 };
423 
425 template< typename T >
427 { return ValueRestorer< T >{ var }; }
428 
429 template< typename T >
430 ValueRestorer< T > valueRestorer( T& var, const T& newValue )
431 { return ValueRestorer< T >{ var, newValue }; }
432 
436 template <typename Iterator>
437 struct IteratorRange : public std::pair<Iterator, Iterator> {
438  using iterator = Iterator;
439  using reverse_iterator = std::reverse_iterator<Iterator>;
440 
441  IteratorRange (const Iterator &a, const Iterator &b)
442  : std::pair<Iterator, Iterator> ( a, b ) {}
443 
444  IteratorRange (Iterator &&a, Iterator &&b)
445  : std::pair<Iterator, Iterator> ( std::move(a), std::move(b) ) {}
446 
448  { return { this->rbegin(), this->rend() }; }
449 
450  Iterator begin() const { return this->first; }
451  Iterator end() const { return this->second; }
452 
453  reverse_iterator rbegin() const { return reverse_iterator{ this->second }; }
454  reverse_iterator rend() const { return reverse_iterator{ this->first }; }
455 
456  bool empty() const { return this->begin() == this->end(); }
457  explicit operator bool () const { return !this->empty(); }
458  size_t size() const { return std::distance(this->begin(), this->end()); }
459 
460  template <typename T> iterator find(const T &t) const
461  { return std::find(this->begin(), this->end(), t); }
462 
463  template <typename T> long index(const T &t) const
464  {
465  auto iter = this->find(t);
466  if (iter == this->end())
467  return -1;
468  return std::distance(this->begin(), iter);
469  }
470 
471  template <typename T> bool contains(const T &t) const
472  { return this->end() != this->find(t); }
473 
474  template <typename F> iterator find_if(const F &f) const
475  { return std::find_if(this->begin(), this->end(), f); }
476 
477  template <typename F> long index_if(const F &f) const
478  {
479  auto iter = this->find_if(f);
480  if (iter == this->end())
481  return -1;
482  return std::distance(this->begin(), iter);
483  }
484 
485  // to do: use std::all_of, any_of, none_of when available on all platforms
486  template <typename F> bool all_of(const F &f) const
487  {
488  auto notF =
489  [&](typename std::iterator_traits<Iterator>::reference v)
490  { return !f(v); };
491  return !this->any_of( notF );
492  }
493 
494  template <typename F> bool any_of(const F &f) const
495  { return this->end() != this->find_if(f); }
496 
497  template <typename F> bool none_of(const F &f) const
498  { return !this->any_of(f); }
499 
500  template<typename T> struct identity
501  { const T&& operator () (T &&v) const { return std::forward(v); } };
502 
503  // Like std::accumulate, but the iterators implied, and with another
504  // unary operation on the iterator value, pre-composed
505  template<
506  typename R,
507  typename Binary = std::plus< R >,
508  typename Unary = identity< decltype( *std::declval<Iterator>() ) >
509  >
511  R init,
512  Binary binary_op = {},
513  Unary unary_op = {}
514  ) const
515  {
516  R result = init;
517  for (auto&& v : *this)
518  result = binary_op(result, unary_op(v));
519  return result;
520  }
521 
522  // An overload making it more convenient to use with pointers to member
523  // functions
524  template<
525  typename R,
526  typename Binary = std::plus< R >,
527  typename R2, typename C
528  >
530  R init,
531  Binary binary_op,
532  R2 (C :: * pmf) () const
533  ) const
534  {
535  return this->accumulate( init, binary_op, std::mem_fn( pmf ) );
536  }
537 
538  // Some accumulations frequent enough to be worth abbreviation:
539  template<
540  typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
541  typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
542  >
543  R min( Unary unary_op = {} ) const
544  {
545  return this->accumulate(
546  std::numeric_limits< R >::max(),
547  (const R&(*)(const R&, const R&)) std::min,
548  unary_op
549  );
550  }
551 
552  template<
553  typename R2, typename C,
554  typename R = R2
555  >
556  R min( R2 (C :: * pmf) () const ) const
557  {
558  return this->min( std::mem_fn( pmf ) );
559  }
560 
561  template<
562  typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
563  typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
564  >
565  R max( Unary unary_op = {} ) const
566  {
567  return this->accumulate(
568  std::numeric_limits< R >::lowest(),
569  (const R&(*)(const R&, const R&)) std::max,
570  unary_op
571  );
572  }
573 
574  template<
575  typename R2, typename C,
576  typename R = R2
577  >
578  R max( R2 (C :: * pmf) () const ) const
579  {
580  return this->max( std::mem_fn( pmf ) );
581  }
582 
583  template<
584  typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
585  typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
586  >
587  R sum( Unary unary_op = {} ) const
588  {
589  return this->accumulate(
590  R{ 0 },
591  std::plus< R >{},
592  unary_op
593  );
594  }
595 
596  template<
597  typename R2, typename C,
598  typename R = R2
599  >
600  R sum( R2 (C :: * pmf) () const ) const
601  {
602  return this->sum( std::mem_fn( pmf ) );
603  }
604 };
605 
606 template< typename Iterator>
608 make_iterator_range( const Iterator &i1, const Iterator &i2 )
609 {
610  return { i1, i2 };
611 }
612 
613 template< typename Container >
615 make_iterator_range( Container &container )
616 {
617  return { container.begin(), container.end() };
618 }
619 
620 template< typename Container >
622 make_iterator_range( const Container &container )
623 {
624  return { container.begin(), container.end() };
625 }
626 
627 #if !wxCHECK_VERSION(3, 1, 0)
628 // For using std::unordered_map on wxString
629 namespace std
630 {
631  template<typename T> struct hash;
632  template<> struct hash< wxString > {
633  size_t operator () (const wxString &str) const // noexcept
634  {
635  auto stdstr = str.ToStdWstring(); // no allocations, a cheap fetch
636  using Hasher = hash< decltype(stdstr) >;
637  return Hasher{}( stdstr );
638  }
639  };
640 }
641 #endif
642 
643 #endif // __AUDACITY_MEMORY_X_H__
Maybe & operator=(const Maybe &that)
Definition: MemoryX.h:222
void operator()(T *p) const
Definition: MemoryX.h:395
R min(R2(C::*pmf)() const ) const
Definition: MemoryX.h:556
memory.h template class for making an array of arrays.
Definition: MemoryX.h:136
bool contains(const T &t) const
Definition: MemoryX.h:471
reverse_iterator rend() const
Definition: MemoryX.h:454
iterator find(const T &t) const
Definition: MemoryX.h:460
reverse_iterator rbegin() const
Definition: MemoryX.h:453
const T && operator()(T &&v) const
Definition: MemoryX.h:501
IteratorRange(Iterator &&a, Iterator &&b)
Definition: MemoryX.h:444
bool none_of(const F &f) const
Definition: MemoryX.h:497
char storage[sizeof(X)]
Definition: MemoryX.h:315
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:113
X * address()
Definition: MemoryX.h:301
R min(Unary unary_op={}) const
Definition: MemoryX.h:543
ArraysOf(Integral1 N, Integral2 M, bool initialize=false)
Definition: MemoryX.h:147
Final_action(F f)
Definition: MemoryX.h:373
void reinit(Integral count, bool initialize)
Definition: MemoryX.h:171
~Maybe()
Definition: MemoryX.h:265
Like a smart pointer, allows for object to not exist (nullptr)
Definition: MemoryX.h:209
A convenience for use with range-for.
Definition: MemoryX.h:437
ArrayOf & operator=(ArrayOf &&that)
Definition: MemoryX.h:101
"finally" as in The C++ Programming Language, 4th ed., p. 358 Useful for defining ad-hoc RAII actions...
Definition: MemoryX.h:372
R accumulate(R init, Binary binary_op={}, Unary unary_op={}) const
Definition: MemoryX.h:510
void reset()
Definition: MemoryX.h:288
IteratorRange< reverse_iterator > reversal() const
Definition: MemoryX.h:447
bool any_of(const F &f) const
Definition: MemoryX.h:494
iterator find_if(const F &f) const
Definition: MemoryX.h:474
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:345
~Final_action()
Definition: MemoryX.h:374
R accumulate(R init, Binary binary_op, R2(C::*pmf)() const ) const
Definition: MemoryX.h:529
Iterator begin() const
Definition: MemoryX.h:450
ArrayOf(Integral count, bool initialize=false)
Definition: MemoryX.h:88
IteratorRange(const Iterator &a, const Iterator &b)
Definition: MemoryX.h:441
unique_ptr< X > scalar_case
Definition: MemoryX.h:40
Structure used by ValueRestorer.
Definition: MemoryX.h:393
ValueRestorer & operator=(ValueRestorer &&that)
Definition: MemoryX.h:416
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:608
bool empty() const
Definition: MemoryX.h:456
Maybe(const Maybe &that)
Definition: MemoryX.h:216
R sum(R2(C::*pmf)() const ) const
Definition: MemoryX.h:600
int min(int a, int b)
X * operator->() const
Definition: MemoryX.h:278
A deleter class to supply the second template parameter of unique_ptr for classes like wxWindow that ...
Definition: MemoryX.h:353
double d
Definition: MemoryX.h:314
ArrayOf(ArrayOf &&that)
Definition: MemoryX.h:96
R sum(Unary unary_op={}) const
Definition: MemoryX.h:587
ArraysOf & operator=(ArraysOf &&that)
Definition: MemoryX.h:158
ArraysOf(Integral N)
Definition: MemoryX.h:142
X & operator*() const
Dereference, with the usual bad consequences if NULL.
Definition: MemoryX.h:273
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
Definition: MemoryX.h:426
R max(R2(C::*pmf)() const ) const
Definition: MemoryX.h:578
Definition: MemoryX.h:333
void reinit(Integral count)
Definition: MemoryX.h:165
Set a variable temporarily in a scope.
Definition: MemoryX.h:403
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
Definition: MemoryX.h:82
long index(const T &t) const
Definition: MemoryX.h:463
Maybe()
Definition: MemoryX.h:213
long index_if(const F &f) const
Definition: MemoryX.h:477
X * get() const
Definition: MemoryX.h:283
std::reverse_iterator< TrackIter< TrackType > > reverse_iterator
Definition: MemoryX.h:439
std::unique_ptr< T, Destroyer< T >> Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:361
void operator()(void *p) const
Definition: MemoryX.h:333
ValueRestorer(T &var)
Definition: MemoryX.h:408
ArraysOf()
Definition: MemoryX.h:139
X * pp
Definition: MemoryX.h:318
bool all_of(const F &f) const
Definition: MemoryX.h:486
unique_ptr< X[]> array_case
Definition: MemoryX.h:45
std::unique_ptr< T, freer > MallocPtr
Definition: MemoryX.h:339
size_t size() const
Definition: MemoryX.h:458
void reinit(Integral1 countN, Integral2 countM, bool initialize=false)
Definition: MemoryX.h:177
R max(Unary unary_op={}) const
Definition: MemoryX.h:565
void create(Args &&...args)
Definition: MemoryX.h:256
#define safenew
Definition: MemoryX.h:8
void operator()(T *p) const
Definition: MemoryX.h:354
Iterator end() const
Definition: MemoryX.h:451
Maybe(Maybe &&that)
Definition: MemoryX.h:233
ArrayOf()
Definition: MemoryX.h:85