mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-25 08:38:39 +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
|
// C++ standard header <memory> with a few extensions
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#ifndef safenew
|
#ifndef safenew
|
||||||
#define safenew new
|
#define safenew new
|
||||||
#endif
|
#endif
|
||||||
@ -41,6 +40,14 @@ namespace std {
|
|||||||
using std::tr1::static_pointer_cast;
|
using std::tr1::static_pointer_cast;
|
||||||
using std::tr1::remove_reference;
|
using std::tr1::remove_reference;
|
||||||
using std::tr1::is_unsigned;
|
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
|
template<typename X> struct default_delete
|
||||||
{
|
{
|
||||||
@ -316,6 +323,11 @@ namespace std {
|
|||||||
template<typename T> inline T&& forward(typename remove_reference<T>::type&& t)
|
template<typename T> inline T&& forward(typename remove_reference<T>::type&& t)
|
||||||
{ return static_cast<T&&>(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
|
// 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)
|
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);
|
return Final_action<F>(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <wx/utils.h> // for wxMin, wxMax
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set a variable temporarily in a scope
|
* Set a variable temporarily in a scope
|
||||||
*/
|
*/
|
||||||
@ -855,11 +870,268 @@ ValueRestorer< T > valueRestorer( T& var, const T& newValue )
|
|||||||
*/
|
*/
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
struct IteratorRange : public std::pair<Iterator, 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)
|
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 begin() const { return this->first; }
|
||||||
Iterator end() const { return this->second; }
|
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__
|
#endif // __AUDACITY_MEMORY_X_H__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user