You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1649 lines
40 KiB
1649 lines
40 KiB
/* /////////////////////////////////////////////////////////////////////////
|
|
* File: rangelib/algorithms.hpp
|
|
*
|
|
* Purpose: Range algorithms.
|
|
*
|
|
* Created: 4th November 2003
|
|
* Updated: 5th March 2011
|
|
*
|
|
* Thanks to: Pablo Aguilar for requesting r_copy_if(); to Luoyi, for pointing
|
|
* out some gaps in the compatibility with the sequence_range; to
|
|
* Yakov Markovitch for spotting a bug in r_exists_if_1_impl().
|
|
*
|
|
* Home: http://stlsoft.org/
|
|
*
|
|
* Copyright (c) 2003-2011, Matthew Wilson and Synesis Software
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
* - Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
* - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
|
|
* any contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
|
|
/** \file rangelib/algorithms.hpp Range algorithms
|
|
*
|
|
* This file includes the definition of the following algorithms:
|
|
*
|
|
* - r_accumulate()
|
|
* - r_accumulate()
|
|
* - r_copy()
|
|
* - r_copy_if()
|
|
* - r_count()
|
|
* - r_count_if()
|
|
* - r_distance()
|
|
* - r_equal()
|
|
* - r_exists()
|
|
* - r_exists_if()
|
|
* - r_fill()
|
|
* - r_fill_n()
|
|
* - r_find()
|
|
* - r_find_if()
|
|
* - r_for_each()
|
|
* - r_generate()
|
|
* - r_max_element()
|
|
* - r_min_element()
|
|
* - r_replace()
|
|
* - r_replace_copy()
|
|
* - r_replace_if()
|
|
* - r_replace_copy_if()
|
|
*/
|
|
|
|
#ifndef RANGELIB_INCL_RANGELIB_HPP_ALGORITHMS
|
|
#define RANGELIB_INCL_RANGELIB_HPP_ALGORITHMS
|
|
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
# define RANGELIB_VER_RANGELIB_HPP_ALGORITHMS_MAJOR 2
|
|
# define RANGELIB_VER_RANGELIB_HPP_ALGORITHMS_MINOR 3
|
|
# define RANGELIB_VER_RANGELIB_HPP_ALGORITHMS_REVISION 6
|
|
# define RANGELIB_VER_RANGELIB_HPP_ALGORITHMS_EDIT 46
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Auto-generation and compatibility
|
|
*/
|
|
|
|
/*
|
|
[Incompatibilies-start]
|
|
STLSOFT_COMPILER_IS_MSVC: _MSC_VER < 1200
|
|
STLSOFT_COMPILER_IS_MWERKS: (__MWERKS__ & 0xFF00) < 0x3000
|
|
[Incompatibilies-end]
|
|
*/
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Includes
|
|
*/
|
|
|
|
#ifndef RANGELIB_INCL_RANGELIB_HPP_RANGELIB
|
|
# include <rangelib/rangelib.hpp>
|
|
#endif /* !RANGELIB_INCL_RANGELIB_HPP_RANGELIB */
|
|
#ifndef RANGELIB_INCL_RANGELIB_HPP_RANGE_CATEGORIES
|
|
# include <rangelib/range_categories.hpp>
|
|
#endif /* !RANGELIB_INCL_RANGELIB_HPP_RANGE_CATEGORIES */
|
|
#ifndef RANGELIB_INCL_RANGELIB_ERROR_HPP_EXCEPTIONS
|
|
# include <rangelib/error/exceptions.hpp>
|
|
#endif /* !RANGELIB_INCL_RANGELIB_ERROR_HPP_EXCEPTIONS */
|
|
#ifndef RANGELIB_INCL_RANGELIB_HPP_BASIC_INDIRECT_RANGE_ADAPTOR
|
|
# include <rangelib/basic_indirect_range_adaptor.hpp>
|
|
#endif /* !RANGELIB_INCL_RANGELIB_HPP_BASIC_INDIRECT_RANGE_ADAPTOR */
|
|
|
|
#ifndef STLSOFT_INCL_ALGORITHM
|
|
# define STLSOFT_INCL_ALGORITHM
|
|
# include <algorithm>
|
|
#endif /* !STLSOFT_INCL_ALGORITHM */
|
|
#ifndef STLSOFT_INCL_NUMERIC
|
|
# define STLSOFT_INCL_NUMERIC
|
|
# include <numeric>
|
|
#endif /* !STLSOFT_INCL_NUMERIC */
|
|
|
|
#ifdef STLSOFT_UNITTEST
|
|
# include <rangelib/integral_range.hpp>
|
|
# include <rangelib/sequence_range.hpp>
|
|
# include <iterator>
|
|
# include <list>
|
|
#endif /* STLSOFT_UNITTEST */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Namespace
|
|
*/
|
|
|
|
#ifndef RANGELIB_NO_NAMESPACE
|
|
# if defined(_STLSOFT_NO_NAMESPACE) || \
|
|
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
|
|
/* There is no stlsoft namespace, so must define ::rangelib */
|
|
namespace rangelib
|
|
{
|
|
# else
|
|
/* Define stlsoft::rangelib_project */
|
|
|
|
namespace stlsoft
|
|
{
|
|
|
|
namespace rangelib_project
|
|
{
|
|
|
|
# endif /* _STLSOFT_NO_NAMESPACE */
|
|
#endif /* !RANGELIB_NO_NAMESPACE */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Functions
|
|
*/
|
|
|
|
/* *********************************************************
|
|
* accumulate (2)
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline T r_accumulate_2_impl(R r, T val, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r)
|
|
{
|
|
val = val + *r;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline T r_accumulate_2_impl(R r, T val, iterable_range_tag const&)
|
|
{
|
|
return std::accumulate(r.begin(), r.end(), val);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline T r_accumulate_2_impl(R r, T val, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).accumulate(val);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline T r_accumulate_2_impl(R r, T val, indirect_range_tag const&)
|
|
{
|
|
return r.accumulate(val);
|
|
}
|
|
|
|
/** \brief accumulate() for ranges
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param val The initial value
|
|
* \retval The sum of the accumulate items and the initial value
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline T r_accumulate(R r, T val)
|
|
{
|
|
return r_accumulate_2_impl(r, val, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* accumulate (3)
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
, ss_typename_param_k P
|
|
>
|
|
inline T r_accumulate_3_impl(R r, T val, P pred, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r)
|
|
{
|
|
val = pred(val, *r);
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
, ss_typename_param_k P
|
|
>
|
|
inline T r_accumulate_3_impl(R r, T val, P pred, iterable_range_tag const&)
|
|
{
|
|
return std::accumulate(r.begin(), r.end(), val, pred);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
, ss_typename_param_k P
|
|
>
|
|
inline T r_accumulate_2_impl(R r, T val, P pred, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).accumulate(val, pred);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
, ss_typename_param_k P
|
|
>
|
|
inline T r_accumulate_3_impl(R r, T val, P pred, indirect_range_tag const&)
|
|
{
|
|
return r.accumulate(val, pred);
|
|
}
|
|
|
|
/** \brief accumulate() for ranges
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param val The initial value
|
|
* \param pred The predicate applied to each entry
|
|
* \retval The sum of the accumulate items and the initial value
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
, ss_typename_param_k P
|
|
>
|
|
inline T r_accumulate(R r, T val, P pred)
|
|
{
|
|
return r_accumulate_3_impl(r, val, pred, r);
|
|
}
|
|
|
|
|
|
/* *********************************************************
|
|
* copy
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
>
|
|
inline O r_copy_impl(R r, O o, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r, ++o)
|
|
{
|
|
*o = *r;
|
|
}
|
|
|
|
return o;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
>
|
|
inline O r_copy_impl(R r, O o, iterable_range_tag const&)
|
|
{
|
|
return std::copy(r.begin(), r.end(), o);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
>
|
|
inline O r_copy_impl(R r, O o, indirect_range_tag const&)
|
|
{
|
|
return r.copy(o);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
>
|
|
inline O r_copy_impl(R r, O o, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).copy(o);
|
|
}
|
|
|
|
/** \brief Copies the contents of the range to the output iterator
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range whose elements are to be copied
|
|
* \param o The output iterator to receive the elements
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
>
|
|
inline O r_copy(R r, O o)
|
|
{
|
|
return r_copy_impl(r, o, r);
|
|
}
|
|
|
|
|
|
/* *********************************************************
|
|
* copy_if
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
, ss_typename_param_k P
|
|
>
|
|
inline O r_copy_if_impl(R r, O o, P pred, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r)
|
|
{
|
|
if(pred(*r))
|
|
{
|
|
*o = *r;
|
|
|
|
++o;
|
|
}
|
|
}
|
|
|
|
return o;
|
|
}
|
|
|
|
#if 0 /* Not defined, since copy_if() is not in standard, so we reuse the Notional Range implementation */
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
, ss_typename_param_k P
|
|
>
|
|
inline O r_copy_if_impl(R r, O o, P pred, iterable_range_tag const&)
|
|
{
|
|
return std::copy_if(r.begin(), r.end(), o);
|
|
}
|
|
#endif /* 0 */
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
, ss_typename_param_k P
|
|
>
|
|
inline O r_copy_if_impl(R r, O o, P pred, indirect_range_tag const&)
|
|
{
|
|
return r.copy_if(o);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
, ss_typename_param_k P
|
|
>
|
|
inline O r_copy_if_impl(R r, O o, P pred, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).copy_if(o);
|
|
}
|
|
|
|
/** \brief Copies the contents of the range to the output iterator
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range whose elements are to be copied
|
|
* \param o The output iterator to receive the elements
|
|
* \param pred The predicate used to select the elements
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k O
|
|
, ss_typename_param_k P
|
|
>
|
|
inline O r_copy_if(R r, O o, P pred)
|
|
{
|
|
return r_copy_if_impl(r, o, pred, r);
|
|
}
|
|
|
|
|
|
/* *********************************************************
|
|
* count
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_size_t r_count_impl(R r, T const& val, notional_range_tag const&)
|
|
{
|
|
ss_size_t n;
|
|
|
|
for(n = 0; r; ++r)
|
|
{
|
|
if(val == *r)
|
|
{
|
|
++n;
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_size_t r_count_impl(R r, T const& val, iterable_range_tag const&)
|
|
{
|
|
return std::count(r.begin(), r.end(), val);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_size_t r_count_impl(R r, T const& val, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).count(val);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_size_t r_count_impl(R r, T const& val, indirect_range_tag const&)
|
|
{
|
|
return r.count(val);
|
|
}
|
|
|
|
/** \brief Counts the number of instances of a given value in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param val The value to search for
|
|
* \retval The number of elements in the range matching \c val
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_size_t r_count(R r, T const& val)
|
|
{
|
|
return r_count_impl(r, val, r);
|
|
}
|
|
|
|
|
|
/* *********************************************************
|
|
* count_if
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_size_t r_count_if_impl(R r, P pred, notional_range_tag const&)
|
|
{
|
|
ss_size_t n;
|
|
|
|
for(n = 0; r; ++r)
|
|
{
|
|
if(pred(*r))
|
|
{
|
|
++n;
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_size_t r_count_if_impl(R r, P pred, iterable_range_tag const&)
|
|
{
|
|
return std::count_if(r.begin(), r.end(), pred);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_size_t r_count_if_impl(R r, P pred, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).count_if(pred);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_size_t r_count_if_impl(R r, P pred, indirect_range_tag const&)
|
|
{
|
|
return r.count_if(pred);
|
|
}
|
|
|
|
/** \brief Counts the number of instances matching the given predicate in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param pred The predicate applied to each entry
|
|
* \retval The number of elements in the range matching \c val
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_size_t r_count_if(R r, P pred)
|
|
{
|
|
return r_count_if_impl(r, pred, r);
|
|
}
|
|
|
|
|
|
/* *********************************************************
|
|
* distance
|
|
*/
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_ptrdiff_t r_distance_1_impl(R r, notional_range_tag const&)
|
|
{
|
|
ss_ptrdiff_t d = 0;
|
|
|
|
for(; r; ++r, ++d)
|
|
{}
|
|
|
|
return d;
|
|
}
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_ptrdiff_t r_distance_1_impl(R r, iterable_range_tag const&)
|
|
{
|
|
return std::distance(r.begin(), r.end());
|
|
}
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_ptrdiff_t r_distance_1_impl(R r, indirect_range_tag const&)
|
|
{
|
|
return r.distance();
|
|
}
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_ptrdiff_t r_distance_1_impl(R r, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).distance();
|
|
}
|
|
|
|
/** \brief Counts the number of instances in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \retval The number of elements in the range
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template <ss_typename_param_k R>
|
|
inline ss_ptrdiff_t r_distance(R r)
|
|
{
|
|
return r_distance_1_impl(r, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* equal (2)
|
|
*/
|
|
|
|
template< ss_typename_param_k R1
|
|
, ss_typename_param_k R2
|
|
>
|
|
inline ss_bool_t r_equal_1_impl(R1 r1, R2 r2, notional_range_tag const&, notional_range_tag const&)
|
|
{
|
|
for(; r1 && r2; ++r1, ++r2)
|
|
{
|
|
if(*r1 != *r2)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
template< ss_typename_param_k R1
|
|
, ss_typename_param_k R2
|
|
>
|
|
inline ss_bool_t r_equal_1_impl(R1 r1, R2 r2, iterable_range_tag const&, iterable_range_tag const&)
|
|
{
|
|
return std::equal(r1.begin(), r1.end(), r2.begin());
|
|
}
|
|
|
|
/** \brief Determines whether two ranges are equal
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r1 The first range to compare
|
|
* \param r2 The second range to compare
|
|
* \retval true if the first N elements in the second range match the N
|
|
* elements in the first range. If the first range contains more
|
|
* elements than the second, then this function always returns false.
|
|
*
|
|
* \note: Supports Notional and Iterable Range types
|
|
*/
|
|
template< ss_typename_param_k R1
|
|
, ss_typename_param_k R2
|
|
>
|
|
inline ss_bool_t r_equal(R1 r1, R2 r2)
|
|
{
|
|
if(r_distance(r1) > r_distance(r2))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return r_equal_1_impl(r1, r2, r1, r2);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* equal (3)
|
|
*/
|
|
|
|
template< ss_typename_param_k R1
|
|
, ss_typename_param_k R2
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_bool_t r_equal_1_impl(R1 r1, R2 r2, P pred, notional_range_tag const&, notional_range_tag const&)
|
|
{
|
|
for(; r1 && r2; ++r1, ++r2)
|
|
{
|
|
if(!pred(*r1, *r2))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
template< ss_typename_param_k R1
|
|
, ss_typename_param_k R2
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_bool_t r_equal_1_impl(R1 r1, R2 r2, P pred, iterable_range_tag const&, iterable_range_tag const&)
|
|
{
|
|
return std::equal(r1.begin(), r1.end(), r2.begin(), pred);
|
|
}
|
|
|
|
/** \brief Determines whether two ranges are equal, as defined by a predicate
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r1 The first range to compare
|
|
* \param r2 The second range to compare
|
|
* \param pred The predicate which evaluates matches between elements of the two ranges
|
|
* \retval true if the first N elements in the second range match the N elements in the first range.
|
|
*
|
|
* \note: Supports Notional and Iterable Range types
|
|
*/
|
|
template< ss_typename_param_k R1
|
|
, ss_typename_param_k R2
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_bool_t r_equal(R1 r1, R2 r2, P pred)
|
|
{
|
|
STLSOFT_ASSERT(r_distance(r1) <= r_distance(r2));
|
|
|
|
return r_equal_1_impl(r1, r2, pred, r1, r2);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* exists
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_bool_t r_exists_impl(R r, T const& val, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r)
|
|
{
|
|
if(val == *r)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_bool_t r_exists_impl(R r, T const& val, iterable_range_tag const&)
|
|
{
|
|
return std::find(r.begin(), r.end(), val) != r.end();
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_bool_t r_exists_impl(R r, T const& val, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).exists(val);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_bool_t r_exists_impl(R r, T const& val, indirect_range_tag const&)
|
|
{
|
|
return r.exists(val);
|
|
}
|
|
|
|
/** \brief Determines whether the given value exists in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param val The value to search for
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_bool_t r_exists(R r, T const& val)
|
|
{
|
|
return r_exists_impl(r, val, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* exists_if (1)
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_bool_t r_exists_if_1_impl(R r, P pred, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r)
|
|
{
|
|
if(pred(*r))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_bool_t r_exists_if_1_impl(R r, P pred, iterable_range_tag const&)
|
|
{
|
|
return std::find_if(r.begin(), r.end(), pred) != r.end();
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_bool_t r_exists_if_1_impl(R r, P pred, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).exists_if(pred);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_bool_t r_exists_if_1_impl(R r, P pred, indirect_range_tag const&)
|
|
{
|
|
return r.exists_if(pred);
|
|
}
|
|
|
|
/** \brief Determines whether a value matching the given predicate exists in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param pred The predicate used to match the items
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline ss_bool_t r_exists_if(R r, P pred)
|
|
{
|
|
return r_exists_if_1_impl(r, pred, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* exists_if (2)
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_bool_t r_exists_if_2_impl(R r, P pred, T &result, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r)
|
|
{
|
|
if(pred(*r))
|
|
{
|
|
result = *r;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template< ss_typename_param_k I
|
|
, ss_typename_param_k V
|
|
>
|
|
inline ss_bool_t r_exists_if_2_impl_helper_(I from, I to, V &val)
|
|
{
|
|
if(from == to)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
val = *from;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_bool_t r_exists_if_2_impl(R r, P pred, T &result, iterable_range_tag const&)
|
|
{
|
|
return r_exists_if_2_impl_helper_(std::find_if(r.begin(), r.end(), pred), r.end());
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_bool_t r_exists_if_2_impl(R r, P pred, T &result, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).exists_if(pred, result);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline ss_bool_t r_exists_if_2_impl(R r, P pred, T &result, indirect_range_tag const&)
|
|
{
|
|
return r.exists_if(pred, result);
|
|
}
|
|
|
|
/** \brief Determines whether a value matching the given predicate exists in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param pred The predicate used to match the items
|
|
* \param result The returned result
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline R r_exists_if(R r, P pred, T &result)
|
|
{
|
|
return r_exists_if_2_impl(r, pred, result, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* fill
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_fill_impl(R r, T const& val, iterable_range_tag const&)
|
|
{
|
|
std::fill(r.begin(), r.end(), val);
|
|
}
|
|
|
|
/** \brief Sets the elements in the range to the given value
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param val The value to assign to all elements in the range
|
|
*
|
|
* \note: Supports Iterable Range type
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_fill(R r, T const& val)
|
|
{
|
|
r_fill_impl(r, val, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* fill_n
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k S
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_fill_n_impl(R r, S n, T const& val, iterable_range_tag const&)
|
|
{
|
|
std::fill(r.begin(), n, val);
|
|
}
|
|
|
|
/** \brief Sets the first \c n elements in the range to the given value
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param n The number of elements to set. This must be <code><= r_distance(r)</code>
|
|
* \param val The value to assign to all elements in the range
|
|
*
|
|
* \note: Supports Iterable Range type
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k S
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_fill_n(R r, S n, T const& val)
|
|
{
|
|
STLSOFT_ASSERT(n <= r_distance(r));
|
|
|
|
r_fill_1_impl(r, n, val, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* find
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline R r_find_impl(R r, T const& val, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r)
|
|
{
|
|
if(val == *r)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline R r_find_impl(R r, T const& val, iterable_range_tag const&)
|
|
{
|
|
return R(std::find(r.begin(), r.end(), val), r.end());
|
|
}
|
|
|
|
/** \brief Finds the first instance of the given value in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param val The value to find
|
|
*
|
|
* \note: Supports Notional and Iterable Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline R r_find(R r, T const& val)
|
|
{
|
|
return r_find_impl(r, val, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* find_if
|
|
*/
|
|
|
|
// find_if
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline R r_find_if_impl(R r, P pred, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r)
|
|
{
|
|
if(pred(*r))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline R r_find_if_impl(R r, P pred, iterable_range_tag const&)
|
|
{
|
|
return R(std::find_if(r.begin(), r.end(), pred), r.end());
|
|
}
|
|
|
|
/** \brief Finds the first instance of a value in the range matching the given predicate
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param pred The value to find
|
|
*
|
|
* \note: Supports Notional and Iterable Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
>
|
|
inline R r_find_if(R r, P pred)
|
|
{
|
|
return r_find_if_impl(r, pred, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* for_each
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline F r_for_each_impl(R r, F f, notional_range_tag const&)
|
|
{
|
|
for(; r; ++r)
|
|
{
|
|
f(*r);
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline F r_for_each_impl(R r, F f, iterable_range_tag const&)
|
|
{
|
|
return std::for_each(r.begin(), r.end(), f);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline F r_for_each_impl(R r, F f, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).for_each(f);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline F r_for_each_impl(R r, F f, indirect_range_tag const&)
|
|
{
|
|
return r.for_each(f);
|
|
}
|
|
|
|
/** \brief Applies the given function to every element in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param f The function to apply
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline F r_for_each(R r, F f)
|
|
{
|
|
return r_for_each_impl(r, f, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* generate
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline void r_generate_impl(R r, F f, iterable_range_tag const&)
|
|
{
|
|
std::generate(r.begin(), r.end(), f);
|
|
}
|
|
|
|
/** \brief Sets each element in the range to the result of the given function
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param f The generator function
|
|
*
|
|
* \note: Supports Iterable Range type
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline void r_generate(R r, F f)
|
|
{
|
|
r_generate_impl(r, f, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* max_element (1)
|
|
*/
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element_1_impl(R r, notional_range_tag const&)
|
|
{
|
|
typedef ss_typename_type_k R::value_type value_type_t;
|
|
|
|
value_type_t max_ = value_type_t();
|
|
|
|
for(; r; ++r)
|
|
{
|
|
if(max_ < *r)
|
|
{
|
|
max_ = *r;
|
|
}
|
|
}
|
|
|
|
return max_;
|
|
}
|
|
|
|
template <ss_typename_param_k I>
|
|
inline I r_max_element_1_impl_iterable(I from, I to)
|
|
{
|
|
if(from == to)
|
|
{
|
|
STLSOFT_THROW_X(empty_range_exception("Cannot determine maximum element of empty range"));
|
|
}
|
|
|
|
return std::max_element(from, to);
|
|
}
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element_1_impl(R r, iterable_range_tag const&)
|
|
{
|
|
return *r_max_element_1_impl_iterable(r.begin(), r.end());
|
|
}
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element_1_impl(R r, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).max_element();
|
|
}
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element_1_impl(R r, indirect_range_tag const&)
|
|
{
|
|
return r.max_element();
|
|
}
|
|
|
|
/** \brief Evaluates the maximum element in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range. Cannot be closed
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
* \note: The behaviour is undefined if the range is closed
|
|
*/
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element(R r)
|
|
{
|
|
STLSOFT_ASSERT(r_distance(r) > 0);
|
|
|
|
return r_max_element_1_impl(r, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* max_element (2)
|
|
*/
|
|
|
|
template< ss_typename_param_k I
|
|
, ss_typename_param_k F
|
|
>
|
|
inline I r_max_element_2_impl_iterable(I from, I to, F f)
|
|
{
|
|
if(from == to)
|
|
{
|
|
STLSOFT_THROW_X(empty_range_exception("Cannot determine maximum element of empty range"));
|
|
}
|
|
|
|
return std::max_element(from, to, f);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element_2_impl(R r, F f, iterable_range_tag const&)
|
|
{
|
|
return *r_max_element_2_impl_iterable(r.begin(), r.end(), f);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element_2_impl(R r, F f, notional_range_tag const&)
|
|
{
|
|
typedef ss_typename_type_k R::value_type value_type_t;
|
|
|
|
value_type_t max_ = value_type_t();
|
|
|
|
for(; r; ++r)
|
|
{
|
|
if(f(max_, *r))
|
|
{
|
|
max_ = *r;
|
|
}
|
|
}
|
|
|
|
return max_;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element_2_impl(R r, F f, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).max_element(f);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element_2_impl(R r, F f, indirect_range_tag const&)
|
|
{
|
|
return r.max_element(f);
|
|
}
|
|
|
|
/** \brief Evaluates the maximum element in the range evaluated according to the given function
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range. Cannot be closed
|
|
* \param f The function used to evaluate the ordering
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
* \note: The behaviour is undefined if the range is closed
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_max_element(R r, F f)
|
|
{
|
|
STLSOFT_ASSERT(r_distance(r) > 0);
|
|
|
|
return r_max_element_2_impl(r, f, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* min_element (1)
|
|
*/
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element_1_impl(R r, notional_range_tag const&)
|
|
{
|
|
typedef ss_typename_type_k R::value_type value_type_t;
|
|
|
|
if(!r)
|
|
{
|
|
return value_type_t();
|
|
}
|
|
else
|
|
{
|
|
value_type_t min_ = *r;
|
|
|
|
for(; ++r; )
|
|
{
|
|
if(*r < min_)
|
|
{
|
|
min_ = *r;
|
|
}
|
|
}
|
|
|
|
return min_;
|
|
}
|
|
}
|
|
|
|
template <ss_typename_param_k I>
|
|
inline I r_min_element_1_impl_iterable(I from, I to)
|
|
{
|
|
if(from == to)
|
|
{
|
|
STLSOFT_THROW_X(empty_range_exception("Cannot determine minimum element of empty range"));
|
|
}
|
|
|
|
return std::min_element(from, to);
|
|
}
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element_1_impl(R r, iterable_range_tag const&)
|
|
{
|
|
return *r_min_element_1_impl_iterable(r.begin(), r.end());
|
|
}
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element_1_impl(R r, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).min_element();
|
|
}
|
|
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element_1_impl(R r, indirect_range_tag const&)
|
|
{
|
|
return r.min_element();
|
|
}
|
|
|
|
/** \brief Evaluates the minimum element in the range
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range. Cannot be closed
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
* \note: The behaviour is undefined if the range is closed
|
|
*/
|
|
template <ss_typename_param_k R>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element(R r)
|
|
{
|
|
STLSOFT_ASSERT(r_distance(r) > 0);
|
|
|
|
return r_min_element_1_impl(r, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* min_element (2)
|
|
*/
|
|
|
|
template< ss_typename_param_k I
|
|
, ss_typename_param_k F
|
|
>
|
|
inline I r_min_element_2_impl_iterable(I from, I to, F f)
|
|
{
|
|
if(from == to)
|
|
{
|
|
STLSOFT_THROW_X(empty_range_exception("Cannot determine minimum element of empty range"));
|
|
}
|
|
|
|
return std::min_element(from, to, f);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element_2_impl(R r, F f, iterable_range_tag const&)
|
|
{
|
|
return *r_min_element_2_impl_iterable(r.begin(), r.end(), f);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element_2_impl(R r, F f, notional_range_tag const&)
|
|
{
|
|
typedef ss_typename_type_k R::value_type value_type_t;
|
|
|
|
value_type_t min_ = value_type_t();
|
|
|
|
for(; r; ++r)
|
|
{
|
|
if(f(min_, *r))
|
|
{
|
|
min_ = *r;
|
|
}
|
|
}
|
|
|
|
return min_;
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element_2_impl(R r, F f, basic_indirect_range_tag const&)
|
|
{
|
|
return indirect_range_adaptor<R>(r).min_element(f);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element_2_impl(R r, F f, indirect_range_tag const&)
|
|
{
|
|
return r.min_element(f);
|
|
}
|
|
|
|
/** \brief Evaluates the minimum element in the range evaluated according to the given function
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range. Cannot be closed
|
|
* \param f The function used to evaluate the ordering
|
|
*
|
|
* \note: Supports Notional, Iterable and Indirect Range types
|
|
* \note: The behaviour is undefined if the range is closed
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k F
|
|
>
|
|
inline ss_typename_type_ret_k R::value_type r_min_element(R r, F f)
|
|
{
|
|
STLSOFT_ASSERT(r_distance(r) > 0);
|
|
|
|
return r_min_element_2_impl(r, f, r);
|
|
}
|
|
|
|
/* *********************************************************
|
|
* replace
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_impl(R r, T oldVal, T newVal, iterable_range_tag const&)
|
|
{
|
|
std::replace(r.begin(), r.end(), oldVal, newVal);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_impl(R r, T oldVal, T newVal, indirect_range_tag const&)
|
|
{
|
|
r.replace(r, oldVal, newVal);
|
|
}
|
|
|
|
|
|
/** \brief Replaces all elements of the given old value with the new value
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param oldVal The value to search for
|
|
* \param newVal The value to replace any elements with \c oldVal
|
|
*
|
|
* \note: Supports Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace(R r, T oldVal, T newVal)
|
|
{
|
|
r_replace_impl(r, oldVal, newVal, r);
|
|
}
|
|
|
|
|
|
/* *********************************************************
|
|
* replace_copy
|
|
*/
|
|
|
|
#if 0
|
|
template< ss_typename_param_k RI
|
|
, ss_typename_param_k RO
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_copy_impl(RI ri, RO ro, T oldVal, T newVal, iterable_range_tag const&, iterable_range_tag const&)
|
|
{
|
|
std::replace_copy(ri.begin(), ri.end(), ro.begin(), oldVal, newVal);
|
|
}
|
|
|
|
template< ss_typename_param_k RI
|
|
, ss_typename_param_k RO
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_copy_impl(RI ri, RO ro, T oldVal, T newVal, indirect_range_tag const&, indirect_range_tag const&)
|
|
{
|
|
ri.replace_copy(ro, oldVal, newVal);
|
|
}
|
|
|
|
/** \brief Replaces all elements of the given old value with the new value
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param oldVal The value to search for
|
|
* \param newVal The value to replace any elements with \c oldVal
|
|
*
|
|
* \note: Supports Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k RI
|
|
, ss_typename_param_k RO
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_copy(RI ri, RO ro, T oldVal, T newVal)
|
|
{
|
|
r_replace_copy_impl(ri, ro, oldVal, newVal, ri, ro);
|
|
}
|
|
#endif /* 0 */
|
|
|
|
/* *********************************************************
|
|
* replace_if
|
|
*/
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_if_impl(R r, P pred, T newVal, iterable_range_tag const&)
|
|
{
|
|
std::replace_if(r.begin(), r.end(), pred, newVal);
|
|
}
|
|
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_if_impl(R r, P pred, T newVal, indirect_range_tag const&)
|
|
{
|
|
r.replace_if(r, pred, newVal);
|
|
}
|
|
|
|
/** \brief Replaces all elements matching the given predicate with the new value
|
|
*
|
|
* \ingroup group__library__rangelib
|
|
*
|
|
* \param r The range
|
|
* \param pred The predicate for matching the old values to replace
|
|
* \param newVal The value to replace any elements which match the given predicate
|
|
*
|
|
* \note: Supports Iterable and Indirect Range types
|
|
*/
|
|
template< ss_typename_param_k R
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_if(R r, P pred, T newVal)
|
|
{
|
|
r_replace_if_impl(r, pred, newVal, r);
|
|
}
|
|
|
|
|
|
/* *********************************************************
|
|
* replace_copy_if
|
|
*/
|
|
|
|
#if 0
|
|
template< ss_typename_param_k RI
|
|
, ss_typename_param_k RO
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_copy_if_impl(RI ri, RO ro, P pred, T newVal, iterable_range_tag const&, iterable_range_tag const&)
|
|
{
|
|
std::replace_copy_if(ri.begin(), ri.end(), ro.begin(), pred, newVal);
|
|
}
|
|
|
|
template< ss_typename_param_k RI
|
|
, ss_typename_param_k RO
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_copy_if_impl(RI ri, RO ro, P pred, T newVal, notional_range_tag const&, notional_range_tag const&)
|
|
{
|
|
for(; ri; ++ri, ++ro)
|
|
{
|
|
STLSOFT_ASSERT(!(!ro));
|
|
|
|
if(pred(*ri))
|
|
{
|
|
*ro = newVal;
|
|
}
|
|
}
|
|
}
|
|
|
|
template< ss_typename_param_k RI
|
|
, ss_typename_param_k RO
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_copy_if_impl(RI ri, RO ro, P pred, T newVal, indirect_range_tag const&, indirect_range_tag const&)
|
|
{
|
|
ri.replace_copy_if(ro, pred, newVal);
|
|
}
|
|
|
|
template< ss_typename_param_k RI
|
|
, ss_typename_param_k RO
|
|
, ss_typename_param_k P
|
|
, ss_typename_param_k T
|
|
>
|
|
inline void r_replace_copy_if(RI ri, RO ro, P pred, T newVal)
|
|
{
|
|
r_replace_copy_if_impl(ri, ro, pe, newVal, ri, ro);
|
|
}
|
|
#endif /* 0 */
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// Unit-testing
|
|
|
|
#ifdef STLSOFT_UNITTEST
|
|
# include "./unittest/algorithms_unittest_.h"
|
|
#endif /* STLSOFT_UNITTEST */
|
|
|
|
/* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
#ifndef RANGELIB_NO_NAMESPACE
|
|
# if defined(_STLSOFT_NO_NAMESPACE) || \
|
|
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
|
|
} // namespace rangelib
|
|
# else
|
|
} // namespace rangelib_project
|
|
} // namespace stlsoft
|
|
# endif /* _STLSOFT_NO_NAMESPACE */
|
|
#endif /* !RANGELIB_NO_NAMESPACE */
|
|
|
|
/* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
#endif /* !RANGELIB_INCL_RANGELIB_HPP_ALGORITHMS */
|
|
|
|
/* ///////////////////////////// end of file //////////////////////////// */
|