#ifndef __AUDACITY_MEMORY_X_H__ #define __AUDACITY_MEMORY_X_H__ // C++ standard header with a few extensions #include #include // Needed for free. #ifndef safenew #define safenew new #endif #include #if !(_MSC_VER >= 1800 || __cplusplus >= 201402L) /* replicate the very useful C++14 make_unique for those build environments that don't implement it yet. typical usage: auto p = std::make_unique(ctorArg1, ctorArg2, ... ctorArgN); p->DoSomething(); auto q = std::make_unique(count); q[0].DoSomethingElse(); The first hides naked NEW and DELETE from the source code. The second hides NEW[] and DELETE[]. Both of course ensure destruction if you don't use something like std::move(p) or q.release(). Both expressions require that you identify the type only once, which is brief and less error prone. (Whereas this omission of [] might invite a runtime error: std::unique_ptr q { safenew Myclass[count] }; ) Some C++11 tricks needed here are (1) variadic argument lists and (2) making the compile-time dispatch work correctly. You can't have a partially specialized template function, but you get the effect of that by other metaprogramming means. */ namespace std { // For overloading resolution template struct __make_unique_result { using scalar_case = unique_ptr; }; // Partial specialization of the struct for array case template struct __make_unique_result { using array_case = unique_ptr; using element = X; }; // Now the scalar version of unique_ptr template inline typename __make_unique_result::scalar_case make_unique(Args&&... args) { return typename __make_unique_result::scalar_case { safenew X(forward(args)...) }; } // Now the array version of unique_ptr // The compile-time dispatch trick is that the non-existence // of the scalar_case type makes the above overload // unavailable when the template parameter is explicit template inline typename __make_unique_result::array_case make_unique(size_t count) { return typename __make_unique_result::array_case { safenew typename __make_unique_result::element[count] }; } } #endif /* * ArrayOf * Not to be confused with std::array (which takes a fixed size) or std::vector * This maintains a pointer allocated by NEW X[]. It's cheap: only one pointer, * with no size and capacity information for resizing as for vector, and if X is * a built-in numeric or pointer type, by default there is no zero filling at * allocation time. */ template class ArrayOf : public std::unique_ptr { public: ArrayOf() {} template explicit ArrayOf(Integral count, bool initialize = false) { static_assert(std::is_unsigned::value, "Unsigned arguments only"); reinit(count, initialize); } //ArrayOf(const ArrayOf&) PROHIBITED; ArrayOf(const ArrayOf&) = delete; ArrayOf(ArrayOf&& that) : std::unique_ptr < X[] > (std::move((std::unique_ptr < X[] >&)(that))) { } ArrayOf& operator= (ArrayOf &&that) { std::unique_ptr::operator=(std::move(that)); return *this; } ArrayOf& operator= (std::unique_ptr &&that) { std::unique_ptr::operator=(std::move(that)); return *this; } template< typename Integral > void reinit(Integral count, bool initialize = false) { static_assert(std::is_unsigned::value, "Unsigned arguments only"); if (initialize) // Initialize elements (usually, to zero for a numerical type) std::unique_ptr::reset(safenew X[count]{}); else // Avoid the slight initialization overhead std::unique_ptr::reset(safenew X[count]); } }; /** \class ArrayOf ArraysOf \brief This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better to use std::Array, N> for some small constant N Or use just one array when sub-arrays have a common size and are not large. */ template class ArraysOf : public ArrayOf> { public: ArraysOf() {} template explicit ArraysOf(Integral N) : ArrayOf>( N ) {} template ArraysOf(Integral1 N, Integral2 M, bool initialize = false) : ArrayOf>( N ) { static_assert(std::is_unsigned::value, "Unsigned arguments only"); static_assert(std::is_unsigned::value, "Unsigned arguments only"); for (size_t ii = 0; ii < N; ++ii) (*this)[ii] = ArrayOf{ M, initialize }; } //ArraysOf(const ArraysOf&) PROHIBITED; ArraysOf(const ArraysOf&) =delete; ArraysOf& operator= (ArraysOf&& that) { ArrayOf>::operator=(std::move(that)); return *this; } template< typename Integral > void reinit(Integral count) { ArrayOf>::reinit( count ); } template< typename Integral > void reinit(Integral count, bool initialize) { ArrayOf>::reinit( count, initialize ); } template void reinit(Integral1 countN, Integral2 countM, bool initialize = false) { static_assert(std::is_unsigned::value, "Unsigned arguments only"); static_assert(std::is_unsigned::value, "Unsigned arguments only"); reinit(countN, false); for (size_t ii = 0; ii < countN; ++ii) (*this)[ii].reinit(countM, initialize); } }; /** \class Optional \brief Like a smart pointer, allows for object to not exist (nullptr) \brief emulating some of std::optional of C++17 template class Optional Can be used for monomorphic objects that are stack-allocable, but only conditionally constructed. You might also use it as a member. Initialize with emplace(), then use like a smart pointer, with *, ->, reset(), or in if() */ // Placement-NEW is used below, and that does not cooperate with the DEBUG_NEW for Visual Studio #ifdef _DEBUG #ifdef _MSC_VER #undef new // wx/any.h also uses Placement-NEW so include it before redefining "new" at comment: // "Restore definition of debug new" #include #endif #endif template class Optional { public: using value_type = X; // Construct as NULL Optional() {} // Supply the copy and move, so you might use this as a class member too Optional(const Optional &that) { if (that) emplace(*that); } Optional& operator= (const Optional &that) { if (this != &that) { if (that) emplace(*that); else reset(); } return *this; } Optional(Optional &&that) { if (that) emplace(::std::move(*that)); } Optional& operator= (Optional &&that) { if (this != &that) { if (that) emplace(::std::move(*that)); else reset(); } return *this; } /// Make an object in the buffer, passing constructor arguments, /// but destroying any previous object first /// Note that if constructor throws, we remain in a consistent /// NULL state -- giving exception safety but only weakly /// (previous value was lost if present) template X& emplace(Args&&... args) { // Lose any old value reset(); // emplace NEW value pp = safenew(address()) X(std::forward(args)...); return **this; } // Destroy any object that was built in it ~Optional() { reset(); } // Pointer-like operators /// Dereference, with the usual bad consequences if NULL X &operator* () const { return *pp; } X *operator-> () const { return pp; } void reset() { if (pp) pp->~X(), pp = nullptr; } // So you can say if(ptr) explicit operator bool() const { return pp != nullptr; } bool has_value() const { return pp != nullptr; } private: X* address() { return reinterpret_cast(&storage); } // Data #if 0 typename ::std::aligned_storage< sizeof(X) // , alignof(X) // Not here yet in all compilers >::type storage{}; #else union { double d; char storage[sizeof(X)]; }; #endif X* pp{ nullptr }; }; // Restore definition of debug new #ifdef _DEBUG #ifdef _MSC_VER #undef THIS_FILE static const char THIS_FILE[] = __FILE__; #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__) #endif #endif /** A deleter for pointers obtained with malloc */ struct freer { void operator() (void *p) const { free(p); } }; /** A useful alias for holding the result of malloc */ template< typename T > using MallocPtr = std::unique_ptr< T, freer >; /** A useful alias for holding the result of strup and similar */ template using MallocString = std::unique_ptr< Character[], freer >; /** \brief A deleter class to supply the second template parameter of unique_ptr for classes like wxWindow that should be sent a message called Destroy rather than be deleted directly */ template struct Destroyer { void operator () (T *p) const { if (p) p->Destroy(); } }; /** \brief a convenience for using Destroyer */ template using Destroy_ptr = std::unique_ptr>; /** \brief "finally" as in The C++ Programming Language, 4th ed., p. 358 Useful for defining ad-hoc RAII actions. typical usage: auto cleanup = finally([&]{ ... code; ... }); */ // Construct this from any copyable function object, such as a lambda template struct Final_action { Final_action(F f) : clean( f ) {} ~Final_action() { clean(); } F clean; }; /// \brief Function template with type deduction lets you construct Final_action /// without typing any angle brackets template Final_action finally (F f) { return Final_action(f); } #include // for wxMin, wxMax #include /** \brief Structure used by ValueRestorer */ template< typename T > struct RestoreValue { T oldValue; void operator () ( T *p ) const { if (p) *p = oldValue; } }; /** \brief Set a variable temporarily in a scope */ template< typename T > class ValueRestorer : public std::unique_ptr< T, RestoreValue > { using std::unique_ptr< T, RestoreValue >::reset; // make private // But release() remains public and can be useful to commit a changed value public: explicit ValueRestorer( T &var ) : std::unique_ptr< T, RestoreValue >( &var, { var } ) {} explicit ValueRestorer( T &var, const T& newValue ) : std::unique_ptr< T, RestoreValue >( &var, { var } ) { var = newValue; } ValueRestorer(ValueRestorer &&that) : std::unique_ptr < T, RestoreValue > ( std::move(that) ) {}; ValueRestorer & operator= (ValueRestorer &&that) { if (this != &that) std::unique_ptr < T, RestoreValue >::operator=(std::move(that)); return *this; } }; /// inline functions provide convenient parameter type deduction template< typename T > ValueRestorer< T > valueRestorer( T& var ) { return ValueRestorer< T >{ var }; } template< typename T > ValueRestorer< T > valueRestorer( T& var, const T& newValue ) { return ValueRestorer< T >{ var, newValue }; } /** \brief A convenience for defining iterators that return rvalue types, so that they cooperate correctly with stl algorithms and std::reverse_iterator */ template< typename Value, typename Category = std::forward_iterator_tag > using ValueIterator = std::iterator< Category, const Value, ptrdiff_t, // void pointer type so that operator -> is disabled void, // make "reference type" really the same as the value type const Value >; /** \brief A convenience for use with range-for */ template struct IteratorRange : public std::pair { using iterator = Iterator; using reverse_iterator = std::reverse_iterator; IteratorRange (const Iterator &a, const Iterator &b) : std::pair ( a, b ) {} IteratorRange (Iterator &&a, Iterator &&b) : std::pair ( std::move(a), std::move(b) ) {} IteratorRange< reverse_iterator > reversal () const { return { this->rbegin(), this->rend() }; } Iterator begin() const { return this->first; } Iterator end() const { return this->second; } reverse_iterator rbegin() const { return reverse_iterator{ this->second }; } reverse_iterator rend() const { return reverse_iterator{ this->first }; } bool empty() const { return this->begin() == this->end(); } explicit operator bool () const { return !this->empty(); } size_t size() const { return std::distance(this->begin(), this->end()); } template iterator find(const T &t) const { return std::find(this->begin(), this->end(), t); } template long index(const T &t) const { auto iter = this->find(t); if (iter == this->end()) return -1; return std::distance(this->begin(), iter); } template bool contains(const T &t) const { return this->end() != this->find(t); } template iterator find_if(const F &f) const { return std::find_if(this->begin(), this->end(), f); } template long index_if(const F &f) const { auto iter = this->find_if(f); if (iter == this->end()) return -1; return std::distance(this->begin(), iter); } // to do: use std::all_of, any_of, none_of when available on all platforms template bool all_of(const F &f) const { auto notF = [&](typename std::iterator_traits::reference v) { return !f(v); }; return !this->any_of( notF ); } template bool any_of(const F &f) const { return this->end() != this->find_if(f); } template bool none_of(const F &f) const { return !this->any_of(f); } template struct identity { const T&& operator () (T &&v) const { return std::forward(v); } }; // Like std::accumulate, but the iterators implied, and with another // unary operation on the iterator value, pre-composed template< typename R, typename Binary = std::plus< R >, typename Unary = identity< decltype( *std::declval() ) > > R accumulate( R init, Binary binary_op = {}, Unary unary_op = {} ) const { R result = init; for (auto&& v : *this) result = binary_op(result, unary_op(v)); return result; } // An overload making it more convenient to use with pointers to member // functions template< typename R, typename Binary = std::plus< R >, typename R2, typename C > R accumulate( R init, Binary binary_op, R2 (C :: * pmf) () const ) const { return this->accumulate( init, binary_op, std::mem_fn( pmf ) ); } // Some accumulations frequent enough to be worth abbreviation: template< typename Unary = identity< decltype( *std::declval() ) >, typename R = decltype( std::declval()( *std::declval() ) ) > R min( Unary unary_op = {} ) const { return this->accumulate( std::numeric_limits< R >::max(), (const R&(*)(const R&, const R&)) std::min, unary_op ); } template< typename R2, typename C, typename R = R2 > R min( R2 (C :: * pmf) () const ) const { return this->min( std::mem_fn( pmf ) ); } template< typename Unary = identity< decltype( *std::declval() ) >, typename R = decltype( std::declval()( *std::declval() ) ) > R max( Unary unary_op = {} ) const { return this->accumulate( std::numeric_limits< R >::lowest(), (const R&(*)(const R&, const R&)) std::max, unary_op ); } template< typename R2, typename C, typename R = R2 > R max( R2 (C :: * pmf) () const ) const { return this->max( std::mem_fn( pmf ) ); } template< typename Unary = identity< decltype( *std::declval() ) >, typename R = decltype( std::declval()( *std::declval() ) ) > R sum( Unary unary_op = {} ) const { return this->accumulate( R{ 0 }, std::plus< R >{}, unary_op ); } template< typename R2, typename C, typename R = R2 > R sum( R2 (C :: * pmf) () const ) const { return this->sum( std::mem_fn( pmf ) ); } }; template< typename Iterator> IteratorRange< Iterator > make_iterator_range( const Iterator &i1, const Iterator &i2 ) { return { i1, i2 }; } template< typename Container > IteratorRange< typename Container::iterator > make_iterator_range( Container &container ) { return { container.begin(), container.end() }; } template< typename Container > IteratorRange< typename Container::const_iterator > make_iterator_range( const Container &container ) { return { container.begin(), container.end() }; } // A utility function building a container of results template< typename Container, typename Iterator, typename Function > Container transform_range( Iterator first, Iterator last, Function &&fn ) { Container result; std::transform( first, last, std::back_inserter( result ), fn ); return result; } // A utility function, often constructing a vector from another vector template< typename OutContainer, typename InContainer, typename Function > OutContainer transform_container( InContainer &inContainer, Function &&fn ) { return transform_range( inContainer.begin(), inContainer.end(), fn ); } // Extend wxArrayString with move operations and construction and insertion from // std::initializer_list class wxArrayStringEx : public wxArrayString { public: using wxArrayString::wxArrayString; wxArrayStringEx() = default; template< typename Iterator > wxArrayStringEx( Iterator start, Iterator finish ) { this->reserve( std::distance( start, finish ) ); while( start != finish ) this->push_back( *start++ ); } template< typename T > wxArrayStringEx( std::initializer_list< T > items ) { this->reserve( this->size() + items.size() ); for ( const auto &item : items ) this->push_back( item ); } // The move operations can take arguments of the base class wxArrayString wxArrayStringEx( wxArrayString &&other ) { swap( other ); } wxArrayStringEx &operator= ( wxArrayString &&other ) { if ( this != &other ) { clear(); swap( other ); } return *this; } using wxArrayString::insert; template< typename T > iterator insert( const_iterator pos, std::initializer_list< T > items ) { const auto index = pos - ((const wxArrayString*)this)->begin(); this->wxArrayString::Insert( {}, index, items.size() ); auto result = this->begin() + index, iter = result; for ( auto pItem = items.begin(), pEnd = items.end(); pItem != pEnd; ++pItem, ++iter ) { *iter = *pItem; } return result; } }; #endif // __AUDACITY_MEMORY_X_H__