From 2cdf931e5ae0c806e8044009deaa68cd80f25e07 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 1 Jan 2018 09:59:35 -0500 Subject: [PATCH] More IteratorRange utility functions and member functions --- src/MemoryX.h | 276 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 274 insertions(+), 2 deletions(-) diff --git a/src/MemoryX.h b/src/MemoryX.h index aab796c87..5df78e750 100644 --- a/src/MemoryX.h +++ b/src/MemoryX.h @@ -3,7 +3,6 @@ // C++ standard header with a few extensions #include - #ifndef safenew #define safenew new #endif @@ -41,6 +40,14 @@ namespace std { using std::tr1::static_pointer_cast; using std::tr1::remove_reference; using std::tr1::is_unsigned; + using std::tr1::is_const; + using std::tr1::add_const; + using std::tr1::add_pointer; + using std::tr1::remove_pointer; + + template struct add_rvalue_reference { + using type = T&&; + }; template struct default_delete { @@ -316,6 +323,11 @@ namespace std { template inline T&& forward(typename remove_reference::type&& t) { return static_cast(t); } + // Declared but never defined, and typically used in decltype constructs + template + typename std::add_rvalue_reference::type declval() //noexcept + ; + // We need make_shared for ourselves, because the library doesn't use variadics template inline shared_ptr make_shared(Args&&... args) { @@ -810,6 +822,9 @@ Final_action finally (F f) return Final_action(f); } +#include // for wxMin, wxMax +#include + /* * Set a variable temporarily in a scope */ @@ -855,11 +870,268 @@ ValueRestorer< T > valueRestorer( T& var, const T& newValue ) */ 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) ) {} + : 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 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); } + + // 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_fun( 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_fun( 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 >::max(), + // std::numeric_limits< R >::lowest(), // TODO C++11 + (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_fun( 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_fun( 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() }; +} + +/* + * Transform an iterator sequence, as another iterator sequence + */ +template < + typename Result, + typename Iterator +> +class transform_iterator + : public std::iterator< + typename std::iterator_traits::iterator_category, + const Result + > +{ + // This takes a function on iterators themselves, not on the + // dereference of those iterators, in case you ever need the generality. + using Function = std::function< Result( const Iterator& ) >; + +private: + Iterator mIterator; + Function mFunction; + +public: + transform_iterator(const Iterator &iterator, const Function &function) + : mIterator( iterator ) + , mFunction( function ) + {} + + transform_iterator &operator ++ () + { ++this->mIterator; return *this; } + transform_iterator operator ++ (int) + { auto copy{*this}; ++this->mIterator; return copy; } + transform_iterator &operator -- () + { --this->mIterator; return *this; } + transform_iterator operator -- (int) + { auto copy{*this}; --this->mIterator; return copy; } + + typename transform_iterator::reference operator * () + { return this->mFunction(this->mIterator); } + + friend inline bool operator == ( + const transform_iterator &a, const transform_iterator &b) + { return a.mIterator == b.mIterator; } + friend inline bool operator != ( + const transform_iterator &a, const transform_iterator &b) + { return !(a == b); } +}; + +template < + typename Iterator, + typename Function +> +transform_iterator< + decltype( std::declval() ( std::declval() ) ), + Iterator +> +make_transform_iterator(const Iterator &iterator, Function function) +{ + return { iterator, function }; +} + +template < typename Function, typename Iterator > struct value_transformer +{ + // Adapts a function on values to a function on iterators. + Function function; + + auto operator () (const Iterator &iterator) + -> decltype( function( *iterator ) ) const + { return this->function( *iterator ); } +}; + +template < + typename Function, + typename Iterator +> +using value_transform_iterator = transform_iterator< + decltype( std::declval()( *std::declval() ) ), + Iterator +>; + +template < + typename Function, + typename Iterator +> +value_transform_iterator< Function, Iterator > +make_value_transform_iterator(const Iterator &iterator, Function function) +{ + using NewFunction = value_transformer; + return { iterator, NewFunction{ function } }; +} + #endif // __AUDACITY_MEMORY_X_H__