#ifndef ERASE_IF_20051208_PATE #define ERASE_IF_20051208_PATE /* Copyright (c) Roger Pate Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Author: Roger Pate You are encouraged to tell me where this code is useful. Bug reports are always appreciated. */ #include "erase_if_detail.hpp" #include namespace Kniht { /// Erases @p where from @p container and returns the iterator for the next element. template< typename Container, typename Iterator > Iterator erase( Container& container, Iterator where ) { return EraseDetail::select_erase(&Container::erase).erase( container, where ); } /// Convenience for @c std::remove_if and @c Container::erase template< typename Container, typename Iterator, typename Predicate > Container& erase_if( Container& c, Iterator begin, Iterator end, Predicate predicate ) { c.erase( std::remove_if( begin, end, predicate ), end ); return c; } /// Convenience for @c erase_if(c,c.begin(),c.end(),predicate) template< typename Container, typename Predicate > Container& erase_if( Container& c, Predicate predicate ) { return erase_if( c, c.begin(), c.end(), predicate ); } /// Convenience for @c erase_if(c,r.begin(),r.end(),predicate) template< typename Container, typename Range, typename Predicate > Container& erase_if( Container& c, Range r, Predicate predicate ) { return erase_if( c, r.begin(), r.end(), predicate ); } /// Erases elements E in @p c for which @c predicate(E) is true, up to @p count max. template< typename Container, typename Iterator, typename Predicate > Container& erase_n_if( Container& c, Iterator begin, Iterator end, unsigned count, Predicate predicate ) { // this could be implemented as an adaptor on the predicate that keeps count with std::remove // however, the current implementation doesn't need to check the predicate once the count has been reached if ( count > 0 ) { // find first to remove for ( ; begin != end; ++begin ) { if ( predicate( *begin ) ) { // 'next' position to store non-removal Iterator next = begin; ++begin; --count; // removal for ( ; count > 0 && begin != end; ++begin ) { if ( !predicate( *begin ) ) { // move non-removed std::swap( *next, *begin ); ++next; } else { --count; } } // move rest for ( ; begin != end; ++next, ++begin ) { std::swap( *next, *begin ); } // erase removed elements c.erase( next, end ); break; } } } return c; } /// Convenience for @c erase_n_if(c,c.begin(),c.end(),count,predicate) template< typename Container, typename Predicate > Container& erase_n_if( Container& c, unsigned count, Predicate predicate ) { return erase_n_if( c, c.begin(), c.end(), count, predicate ); } /// Convenience for @c erase_n_if(c,r.begin(),r.end(),count,predicate) template< typename Container, typename Range, typename Predicate > Container& erase_n_if( Container& c, Range r, unsigned count, Predicate predicate ) { return erase_n_if( c, r.begin(), r.end(), count, predicate ); } /** @brief Erases depending on the container rather than individual elements For each N in [begin,c.end()), while ( predicate(c) ) is true, immediately erases N from c. @note Once predicate(c) is false, the erase is finished. @note I'm not sure this algorithm is actually helpful, let me know if you find a use for it. */ template< typename Container, typename Iterator, typename Predicate > Container& erase_while_to_end( Container& c, Iterator begin, Predicate predicate ) { while ( predicate( c ) && begin != c.end() ) { begin = erase( c, begin ); } return c; } /// Convenience for @c erase_while_to_end(c,c.begin(),predicate) template< typename Container, typename Predicate > Container& erase_while_to_end( Container& c, Predicate predicate ) { return erase_while_to_end( c, c.begin(), predicate ); } } // Kniht:: #endif