mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-25 16:48:44 +02:00
More IteratorRange utility functions and member functions
This commit is contained in:
parent
7ec5fd79df
commit
2cdf931e5a
276
src/MemoryX.h
276
src/MemoryX.h
@ -3,7 +3,6 @@
|
||||
|
||||
// C++ standard header <memory> with a few extensions
|
||||
#include <memory>
|
||||
|
||||
#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<typename T> struct add_rvalue_reference {
|
||||
using type = T&&;
|
||||
};
|
||||
|
||||
template<typename X> struct default_delete
|
||||
{
|
||||
@ -316,6 +323,11 @@ namespace std {
|
||||
template<typename T> inline T&& forward(typename remove_reference<T>::type&& t)
|
||||
{ return static_cast<T&&>(t); }
|
||||
|
||||
// Declared but never defined, and typically used in decltype constructs
|
||||
template<typename T>
|
||||
typename std::add_rvalue_reference<T>::type declval() //noexcept
|
||||
;
|
||||
|
||||
// We need make_shared for ourselves, because the library doesn't use variadics
|
||||
template<typename X, typename... Args> inline shared_ptr<X> make_shared(Args&&... args)
|
||||
{
|
||||
@ -810,6 +822,9 @@ Final_action<F> finally (F f)
|
||||
return Final_action<F>(f);
|
||||
}
|
||||
|
||||
#include <wx/utils.h> // for wxMin, wxMax
|
||||
#include <algorithm>
|
||||
|
||||
/*
|
||||
* Set a variable temporarily in a scope
|
||||
*/
|
||||
@ -855,11 +870,268 @@ ValueRestorer< T > valueRestorer( T& var, const T& newValue )
|
||||
*/
|
||||
template <typename Iterator>
|
||||
struct IteratorRange : public std::pair<Iterator, Iterator> {
|
||||
using iterator = Iterator;
|
||||
using reverse_iterator = std::reverse_iterator<Iterator>;
|
||||
|
||||
IteratorRange (const Iterator &a, const Iterator &b)
|
||||
: std::pair<Iterator, Iterator> ( a, b ) {}
|
||||
|
||||
IteratorRange (Iterator &&a, Iterator &&b)
|
||||
: std::pair<Iterator, Iterator> ( std::move(a), std::move(b) ) {}
|
||||
: std::pair<Iterator, Iterator> ( 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 <typename T> iterator find(const T &t) const
|
||||
{ return std::find(this->begin(), this->end(), t); }
|
||||
|
||||
template <typename T> bool contains(const T &t) const
|
||||
{ return this->end() != this->find(t); }
|
||||
|
||||
template <typename F> 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 <typename F> bool all_of(const F &f) const
|
||||
{
|
||||
auto notF =
|
||||
[&](typename std::iterator_traits<Iterator>::reference v)
|
||||
{ return !f(v); };
|
||||
return !this->any_of( notF );
|
||||
}
|
||||
|
||||
template <typename F> bool any_of(const F &f) const
|
||||
{ return this->end() != this->find_if(f); }
|
||||
|
||||
template <typename F> bool none_of(const F &f) const
|
||||
{ return !this->any_of(f); }
|
||||
|
||||
template<typename T> 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<Iterator>() ) >
|
||||
>
|
||||
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<Iterator>() ) >,
|
||||
typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
|
||||
>
|
||||
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<Iterator>() ) >,
|
||||
typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
|
||||
>
|
||||
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<Iterator>() ) >,
|
||||
typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
|
||||
>
|
||||
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>::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<Function>() ( std::declval<Iterator>() ) ),
|
||||
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<Function>()( *std::declval<Iterator>() ) ),
|
||||
Iterator
|
||||
>;
|
||||
|
||||
template <
|
||||
typename Function,
|
||||
typename Iterator
|
||||
>
|
||||
value_transform_iterator< Function, Iterator >
|
||||
make_value_transform_iterator(const Iterator &iterator, Function function)
|
||||
{
|
||||
using NewFunction = value_transformer<Function, Iterator>;
|
||||
return { iterator, NewFunction{ function } };
|
||||
}
|
||||
|
||||
#endif // __AUDACITY_MEMORY_X_H__
|
||||
|
Loading…
x
Reference in New Issue
Block a user