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

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: rangelib/algorithms.hpp
  3. *
  4. * Purpose: Range algorithms.
  5. *
  6. * Created: 4th November 2003
  7. * Updated: 5th March 2011
  8. *
  9. * Thanks to: Pablo Aguilar for requesting r_copy_if(); to Luoyi, for pointing
  10. * out some gaps in the compatibility with the sequence_range; to
  11. * Yakov Markovitch for spotting a bug in r_exists_if_1_impl().
  12. *
  13. * Home: http://stlsoft.org/
  14. *
  15. * Copyright (c) 2003-2011, Matthew Wilson and Synesis Software
  16. * All rights reserved.
  17. *
  18. * Redistribution and use in source and binary forms, with or without
  19. * modification, are permitted provided that the following conditions are met:
  20. *
  21. * - Redistributions of source code must retain the above copyright notice, this
  22. * list of conditions and the following disclaimer.
  23. * - Redistributions in binary form must reproduce the above copyright notice,
  24. * this list of conditions and the following disclaimer in the documentation
  25. * and/or other materials provided with the distribution.
  26. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  27. * any contributors may be used to endorse or promote products derived from
  28. * this software without specific prior written permission.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  31. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  34. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  35. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  36. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  37. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  38. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  39. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGE.
  41. *
  42. * ////////////////////////////////////////////////////////////////////// */
  43. /** \file rangelib/algorithms.hpp Range algorithms
  44. *
  45. * This file includes the definition of the following algorithms:
  46. *
  47. * - r_accumulate()
  48. * - r_accumulate()
  49. * - r_copy()
  50. * - r_copy_if()
  51. * - r_count()
  52. * - r_count_if()
  53. * - r_distance()
  54. * - r_equal()
  55. * - r_exists()
  56. * - r_exists_if()
  57. * - r_fill()
  58. * - r_fill_n()
  59. * - r_find()
  60. * - r_find_if()
  61. * - r_for_each()
  62. * - r_generate()
  63. * - r_max_element()
  64. * - r_min_element()
  65. * - r_replace()
  66. * - r_replace_copy()
  67. * - r_replace_if()
  68. * - r_replace_copy_if()
  69. */
  70. #ifndef RANGELIB_INCL_RANGELIB_HPP_ALGORITHMS
  71. #define RANGELIB_INCL_RANGELIB_HPP_ALGORITHMS
  72. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  73. # define RANGELIB_VER_RANGELIB_HPP_ALGORITHMS_MAJOR 2
  74. # define RANGELIB_VER_RANGELIB_HPP_ALGORITHMS_MINOR 3
  75. # define RANGELIB_VER_RANGELIB_HPP_ALGORITHMS_REVISION 6
  76. # define RANGELIB_VER_RANGELIB_HPP_ALGORITHMS_EDIT 46
  77. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  78. /* /////////////////////////////////////////////////////////////////////////
  79. * Auto-generation and compatibility
  80. */
  81. /*
  82. [Incompatibilies-start]
  83. STLSOFT_COMPILER_IS_MSVC: _MSC_VER < 1200
  84. STLSOFT_COMPILER_IS_MWERKS: (__MWERKS__ & 0xFF00) < 0x3000
  85. [Incompatibilies-end]
  86. */
  87. /* /////////////////////////////////////////////////////////////////////////
  88. * Includes
  89. */
  90. #ifndef RANGELIB_INCL_RANGELIB_HPP_RANGELIB
  91. # include <rangelib/rangelib.hpp>
  92. #endif /* !RANGELIB_INCL_RANGELIB_HPP_RANGELIB */
  93. #ifndef RANGELIB_INCL_RANGELIB_HPP_RANGE_CATEGORIES
  94. # include <rangelib/range_categories.hpp>
  95. #endif /* !RANGELIB_INCL_RANGELIB_HPP_RANGE_CATEGORIES */
  96. #ifndef RANGELIB_INCL_RANGELIB_ERROR_HPP_EXCEPTIONS
  97. # include <rangelib/error/exceptions.hpp>
  98. #endif /* !RANGELIB_INCL_RANGELIB_ERROR_HPP_EXCEPTIONS */
  99. #ifndef RANGELIB_INCL_RANGELIB_HPP_BASIC_INDIRECT_RANGE_ADAPTOR
  100. # include <rangelib/basic_indirect_range_adaptor.hpp>
  101. #endif /* !RANGELIB_INCL_RANGELIB_HPP_BASIC_INDIRECT_RANGE_ADAPTOR */
  102. #ifndef STLSOFT_INCL_ALGORITHM
  103. # define STLSOFT_INCL_ALGORITHM
  104. # include <algorithm>
  105. #endif /* !STLSOFT_INCL_ALGORITHM */
  106. #ifndef STLSOFT_INCL_NUMERIC
  107. # define STLSOFT_INCL_NUMERIC
  108. # include <numeric>
  109. #endif /* !STLSOFT_INCL_NUMERIC */
  110. #ifdef STLSOFT_UNITTEST
  111. # include <rangelib/integral_range.hpp>
  112. # include <rangelib/sequence_range.hpp>
  113. # include <iterator>
  114. # include <list>
  115. #endif /* STLSOFT_UNITTEST */
  116. /* /////////////////////////////////////////////////////////////////////////
  117. * Namespace
  118. */
  119. #ifndef RANGELIB_NO_NAMESPACE
  120. # if defined(_STLSOFT_NO_NAMESPACE) || \
  121. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  122. /* There is no stlsoft namespace, so must define ::rangelib */
  123. namespace rangelib
  124. {
  125. # else
  126. /* Define stlsoft::rangelib_project */
  127. namespace stlsoft
  128. {
  129. namespace rangelib_project
  130. {
  131. # endif /* _STLSOFT_NO_NAMESPACE */
  132. #endif /* !RANGELIB_NO_NAMESPACE */
  133. /* /////////////////////////////////////////////////////////////////////////
  134. * Functions
  135. */
  136. /* *********************************************************
  137. * accumulate (2)
  138. */
  139. template< ss_typename_param_k R
  140. , ss_typename_param_k T
  141. >
  142. inline T r_accumulate_2_impl(R r, T val, notional_range_tag const&)
  143. {
  144. for(; r; ++r)
  145. {
  146. val = val + *r;
  147. }
  148. return val;
  149. }
  150. template< ss_typename_param_k R
  151. , ss_typename_param_k T
  152. >
  153. inline T r_accumulate_2_impl(R r, T val, iterable_range_tag const&)
  154. {
  155. return std::accumulate(r.begin(), r.end(), val);
  156. }
  157. template< ss_typename_param_k R
  158. , ss_typename_param_k T
  159. >
  160. inline T r_accumulate_2_impl(R r, T val, basic_indirect_range_tag const&)
  161. {
  162. return indirect_range_adaptor<R>(r).accumulate(val);
  163. }
  164. template< ss_typename_param_k R
  165. , ss_typename_param_k T
  166. >
  167. inline T r_accumulate_2_impl(R r, T val, indirect_range_tag const&)
  168. {
  169. return r.accumulate(val);
  170. }
  171. /** \brief accumulate() for ranges
  172. *
  173. * \ingroup group__library__rangelib
  174. *
  175. * \param r The range
  176. * \param val The initial value
  177. * \retval The sum of the accumulate items and the initial value
  178. *
  179. * \note: Supports Notional, Iterable and Indirect Range types
  180. */
  181. template< ss_typename_param_k R
  182. , ss_typename_param_k T
  183. >
  184. inline T r_accumulate(R r, T val)
  185. {
  186. return r_accumulate_2_impl(r, val, r);
  187. }
  188. /* *********************************************************
  189. * accumulate (3)
  190. */
  191. template< ss_typename_param_k R
  192. , ss_typename_param_k T
  193. , ss_typename_param_k P
  194. >
  195. inline T r_accumulate_3_impl(R r, T val, P pred, notional_range_tag const&)
  196. {
  197. for(; r; ++r)
  198. {
  199. val = pred(val, *r);
  200. }
  201. return val;
  202. }
  203. template< ss_typename_param_k R
  204. , ss_typename_param_k T
  205. , ss_typename_param_k P
  206. >
  207. inline T r_accumulate_3_impl(R r, T val, P pred, iterable_range_tag const&)
  208. {
  209. return std::accumulate(r.begin(), r.end(), val, pred);
  210. }
  211. template< ss_typename_param_k R
  212. , ss_typename_param_k T
  213. , ss_typename_param_k P
  214. >
  215. inline T r_accumulate_2_impl(R r, T val, P pred, basic_indirect_range_tag const&)
  216. {
  217. return indirect_range_adaptor<R>(r).accumulate(val, pred);
  218. }
  219. template< ss_typename_param_k R
  220. , ss_typename_param_k T
  221. , ss_typename_param_k P
  222. >
  223. inline T r_accumulate_3_impl(R r, T val, P pred, indirect_range_tag const&)
  224. {
  225. return r.accumulate(val, pred);
  226. }
  227. /** \brief accumulate() for ranges
  228. *
  229. * \ingroup group__library__rangelib
  230. *
  231. * \param r The range
  232. * \param val The initial value
  233. * \param pred The predicate applied to each entry
  234. * \retval The sum of the accumulate items and the initial value
  235. *
  236. * \note: Supports Notional, Iterable and Indirect Range types
  237. */
  238. template< ss_typename_param_k R
  239. , ss_typename_param_k T
  240. , ss_typename_param_k P
  241. >
  242. inline T r_accumulate(R r, T val, P pred)
  243. {
  244. return r_accumulate_3_impl(r, val, pred, r);
  245. }
  246. /* *********************************************************
  247. * copy
  248. */
  249. template< ss_typename_param_k R
  250. , ss_typename_param_k O
  251. >
  252. inline O r_copy_impl(R r, O o, notional_range_tag const&)
  253. {
  254. for(; r; ++r, ++o)
  255. {
  256. *o = *r;
  257. }
  258. return o;
  259. }
  260. template< ss_typename_param_k R
  261. , ss_typename_param_k O
  262. >
  263. inline O r_copy_impl(R r, O o, iterable_range_tag const&)
  264. {
  265. return std::copy(r.begin(), r.end(), o);
  266. }
  267. template< ss_typename_param_k R
  268. , ss_typename_param_k O
  269. >
  270. inline O r_copy_impl(R r, O o, indirect_range_tag const&)
  271. {
  272. return r.copy(o);
  273. }
  274. template< ss_typename_param_k R
  275. , ss_typename_param_k O
  276. >
  277. inline O r_copy_impl(R r, O o, basic_indirect_range_tag const&)
  278. {
  279. return indirect_range_adaptor<R>(r).copy(o);
  280. }
  281. /** \brief Copies the contents of the range to the output iterator
  282. *
  283. * \ingroup group__library__rangelib
  284. *
  285. * \param r The range whose elements are to be copied
  286. * \param o The output iterator to receive the elements
  287. *
  288. * \note: Supports Notional, Iterable and Indirect Range types
  289. */
  290. template< ss_typename_param_k R
  291. , ss_typename_param_k O
  292. >
  293. inline O r_copy(R r, O o)
  294. {
  295. return r_copy_impl(r, o, r);
  296. }
  297. /* *********************************************************
  298. * copy_if
  299. */
  300. template< ss_typename_param_k R
  301. , ss_typename_param_k O
  302. , ss_typename_param_k P
  303. >
  304. inline O r_copy_if_impl(R r, O o, P pred, notional_range_tag const&)
  305. {
  306. for(; r; ++r)
  307. {
  308. if(pred(*r))
  309. {
  310. *o = *r;
  311. ++o;
  312. }
  313. }
  314. return o;
  315. }
  316. #if 0 /* Not defined, since copy_if() is not in standard, so we reuse the Notional Range implementation */
  317. template< ss_typename_param_k R
  318. , ss_typename_param_k O
  319. , ss_typename_param_k P
  320. >
  321. inline O r_copy_if_impl(R r, O o, P pred, iterable_range_tag const&)
  322. {
  323. return std::copy_if(r.begin(), r.end(), o);
  324. }
  325. #endif /* 0 */
  326. template< ss_typename_param_k R
  327. , ss_typename_param_k O
  328. , ss_typename_param_k P
  329. >
  330. inline O r_copy_if_impl(R r, O o, P pred, indirect_range_tag const&)
  331. {
  332. return r.copy_if(o);
  333. }
  334. template< ss_typename_param_k R
  335. , ss_typename_param_k O
  336. , ss_typename_param_k P
  337. >
  338. inline O r_copy_if_impl(R r, O o, P pred, basic_indirect_range_tag const&)
  339. {
  340. return indirect_range_adaptor<R>(r).copy_if(o);
  341. }
  342. /** \brief Copies the contents of the range to the output iterator
  343. *
  344. * \ingroup group__library__rangelib
  345. *
  346. * \param r The range whose elements are to be copied
  347. * \param o The output iterator to receive the elements
  348. * \param pred The predicate used to select the elements
  349. *
  350. * \note: Supports Notional, Iterable and Indirect Range types
  351. */
  352. template< ss_typename_param_k R
  353. , ss_typename_param_k O
  354. , ss_typename_param_k P
  355. >
  356. inline O r_copy_if(R r, O o, P pred)
  357. {
  358. return r_copy_if_impl(r, o, pred, r);
  359. }
  360. /* *********************************************************
  361. * count
  362. */
  363. template< ss_typename_param_k R
  364. , ss_typename_param_k T
  365. >
  366. inline ss_size_t r_count_impl(R r, T const& val, notional_range_tag const&)
  367. {
  368. ss_size_t n;
  369. for(n = 0; r; ++r)
  370. {
  371. if(val == *r)
  372. {
  373. ++n;
  374. }
  375. }
  376. return n;
  377. }
  378. template< ss_typename_param_k R
  379. , ss_typename_param_k T
  380. >
  381. inline ss_size_t r_count_impl(R r, T const& val, iterable_range_tag const&)
  382. {
  383. return std::count(r.begin(), r.end(), val);
  384. }
  385. template< ss_typename_param_k R
  386. , ss_typename_param_k T
  387. >
  388. inline ss_size_t r_count_impl(R r, T const& val, basic_indirect_range_tag const&)
  389. {
  390. return indirect_range_adaptor<R>(r).count(val);
  391. }
  392. template< ss_typename_param_k R
  393. , ss_typename_param_k T
  394. >
  395. inline ss_size_t r_count_impl(R r, T const& val, indirect_range_tag const&)
  396. {
  397. return r.count(val);
  398. }
  399. /** \brief Counts the number of instances of a given value in the range
  400. *
  401. * \ingroup group__library__rangelib
  402. *
  403. * \param r The range
  404. * \param val The value to search for
  405. * \retval The number of elements in the range matching \c val
  406. *
  407. * \note: Supports Notional, Iterable and Indirect Range types
  408. */
  409. template< ss_typename_param_k R
  410. , ss_typename_param_k T
  411. >
  412. inline ss_size_t r_count(R r, T const& val)
  413. {
  414. return r_count_impl(r, val, r);
  415. }
  416. /* *********************************************************
  417. * count_if
  418. */
  419. template< ss_typename_param_k R
  420. , ss_typename_param_k P
  421. >
  422. inline ss_size_t r_count_if_impl(R r, P pred, notional_range_tag const&)
  423. {
  424. ss_size_t n;
  425. for(n = 0; r; ++r)
  426. {
  427. if(pred(*r))
  428. {
  429. ++n;
  430. }
  431. }
  432. return n;
  433. }
  434. template< ss_typename_param_k R
  435. , ss_typename_param_k P
  436. >
  437. inline ss_size_t r_count_if_impl(R r, P pred, iterable_range_tag const&)
  438. {
  439. return std::count_if(r.begin(), r.end(), pred);
  440. }
  441. template< ss_typename_param_k R
  442. , ss_typename_param_k P
  443. >
  444. inline ss_size_t r_count_if_impl(R r, P pred, basic_indirect_range_tag const&)
  445. {
  446. return indirect_range_adaptor<R>(r).count_if(pred);
  447. }
  448. template< ss_typename_param_k R
  449. , ss_typename_param_k P
  450. >
  451. inline ss_size_t r_count_if_impl(R r, P pred, indirect_range_tag const&)
  452. {
  453. return r.count_if(pred);
  454. }
  455. /** \brief Counts the number of instances matching the given predicate in the range
  456. *
  457. * \ingroup group__library__rangelib
  458. *
  459. * \param r The range
  460. * \param pred The predicate applied to each entry
  461. * \retval The number of elements in the range matching \c val
  462. *
  463. * \note: Supports Notional, Iterable and Indirect Range types
  464. */
  465. template< ss_typename_param_k R
  466. , ss_typename_param_k P
  467. >
  468. inline ss_size_t r_count_if(R r, P pred)
  469. {
  470. return r_count_if_impl(r, pred, r);
  471. }
  472. /* *********************************************************
  473. * distance
  474. */
  475. template <ss_typename_param_k R>
  476. inline ss_ptrdiff_t r_distance_1_impl(R r, notional_range_tag const&)
  477. {
  478. ss_ptrdiff_t d = 0;
  479. for(; r; ++r, ++d)
  480. {}
  481. return d;
  482. }
  483. template <ss_typename_param_k R>
  484. inline ss_ptrdiff_t r_distance_1_impl(R r, iterable_range_tag const&)
  485. {
  486. return std::distance(r.begin(), r.end());
  487. }
  488. template <ss_typename_param_k R>
  489. inline ss_ptrdiff_t r_distance_1_impl(R r, indirect_range_tag const&)
  490. {
  491. return r.distance();
  492. }
  493. template <ss_typename_param_k R>
  494. inline ss_ptrdiff_t r_distance_1_impl(R r, basic_indirect_range_tag const&)
  495. {
  496. return indirect_range_adaptor<R>(r).distance();
  497. }
  498. /** \brief Counts the number of instances in the range
  499. *
  500. * \ingroup group__library__rangelib
  501. *
  502. * \param r The range
  503. * \retval The number of elements in the range
  504. *
  505. * \note: Supports Notional, Iterable and Indirect Range types
  506. */
  507. template <ss_typename_param_k R>
  508. inline ss_ptrdiff_t r_distance(R r)
  509. {
  510. return r_distance_1_impl(r, r);
  511. }
  512. /* *********************************************************
  513. * equal (2)
  514. */
  515. template< ss_typename_param_k R1
  516. , ss_typename_param_k R2
  517. >
  518. inline ss_bool_t r_equal_1_impl(R1 r1, R2 r2, notional_range_tag const&, notional_range_tag const&)
  519. {
  520. for(; r1 && r2; ++r1, ++r2)
  521. {
  522. if(*r1 != *r2)
  523. {
  524. return false;
  525. }
  526. }
  527. return true;
  528. }
  529. template< ss_typename_param_k R1
  530. , ss_typename_param_k R2
  531. >
  532. inline ss_bool_t r_equal_1_impl(R1 r1, R2 r2, iterable_range_tag const&, iterable_range_tag const&)
  533. {
  534. return std::equal(r1.begin(), r1.end(), r2.begin());
  535. }
  536. /** \brief Determines whether two ranges are equal
  537. *
  538. * \ingroup group__library__rangelib
  539. *
  540. * \param r1 The first range to compare
  541. * \param r2 The second range to compare
  542. * \retval true if the first N elements in the second range match the N
  543. * elements in the first range. If the first range contains more
  544. * elements than the second, then this function always returns false.
  545. *
  546. * \note: Supports Notional and Iterable Range types
  547. */
  548. template< ss_typename_param_k R1
  549. , ss_typename_param_k R2
  550. >
  551. inline ss_bool_t r_equal(R1 r1, R2 r2)
  552. {
  553. if(r_distance(r1) > r_distance(r2))
  554. {
  555. return false;
  556. }
  557. return r_equal_1_impl(r1, r2, r1, r2);
  558. }
  559. /* *********************************************************
  560. * equal (3)
  561. */
  562. template< ss_typename_param_k R1
  563. , ss_typename_param_k R2
  564. , ss_typename_param_k P
  565. >
  566. inline ss_bool_t r_equal_1_impl(R1 r1, R2 r2, P pred, notional_range_tag const&, notional_range_tag const&)
  567. {
  568. for(; r1 && r2; ++r1, ++r2)
  569. {
  570. if(!pred(*r1, *r2))
  571. {
  572. return false;
  573. }
  574. }
  575. return true;
  576. }
  577. template< ss_typename_param_k R1
  578. , ss_typename_param_k R2
  579. , ss_typename_param_k P
  580. >
  581. inline ss_bool_t r_equal_1_impl(R1 r1, R2 r2, P pred, iterable_range_tag const&, iterable_range_tag const&)
  582. {
  583. return std::equal(r1.begin(), r1.end(), r2.begin(), pred);
  584. }
  585. /** \brief Determines whether two ranges are equal, as defined by a predicate
  586. *
  587. * \ingroup group__library__rangelib
  588. *
  589. * \param r1 The first range to compare
  590. * \param r2 The second range to compare
  591. * \param pred The predicate which evaluates matches between elements of the two ranges
  592. * \retval true if the first N elements in the second range match the N elements in the first range.
  593. *
  594. * \note: Supports Notional and Iterable Range types
  595. */
  596. template< ss_typename_param_k R1
  597. , ss_typename_param_k R2
  598. , ss_typename_param_k P
  599. >
  600. inline ss_bool_t r_equal(R1 r1, R2 r2, P pred)
  601. {
  602. STLSOFT_ASSERT(r_distance(r1) <= r_distance(r2));
  603. return r_equal_1_impl(r1, r2, pred, r1, r2);
  604. }
  605. /* *********************************************************
  606. * exists
  607. */
  608. template< ss_typename_param_k R
  609. , ss_typename_param_k T
  610. >
  611. inline ss_bool_t r_exists_impl(R r, T const& val, notional_range_tag const&)
  612. {
  613. for(; r; ++r)
  614. {
  615. if(val == *r)
  616. {
  617. return true;
  618. }
  619. }
  620. return false;
  621. }
  622. template< ss_typename_param_k R
  623. , ss_typename_param_k T
  624. >
  625. inline ss_bool_t r_exists_impl(R r, T const& val, iterable_range_tag const&)
  626. {
  627. return std::find(r.begin(), r.end(), val) != r.end();
  628. }
  629. template< ss_typename_param_k R
  630. , ss_typename_param_k T
  631. >
  632. inline ss_bool_t r_exists_impl(R r, T const& val, basic_indirect_range_tag const&)
  633. {
  634. return indirect_range_adaptor<R>(r).exists(val);
  635. }
  636. template< ss_typename_param_k R
  637. , ss_typename_param_k T
  638. >
  639. inline ss_bool_t r_exists_impl(R r, T const& val, indirect_range_tag const&)
  640. {
  641. return r.exists(val);
  642. }
  643. /** \brief Determines whether the given value exists in the range
  644. *
  645. * \ingroup group__library__rangelib
  646. *
  647. * \param r The range
  648. * \param val The value to search for
  649. *
  650. * \note: Supports Notional, Iterable and Indirect Range types
  651. */
  652. template< ss_typename_param_k R
  653. , ss_typename_param_k T
  654. >
  655. inline ss_bool_t r_exists(R r, T const& val)
  656. {
  657. return r_exists_impl(r, val, r);
  658. }
  659. /* *********************************************************
  660. * exists_if (1)
  661. */
  662. template< ss_typename_param_k R
  663. , ss_typename_param_k P
  664. >
  665. inline ss_bool_t r_exists_if_1_impl(R r, P pred, notional_range_tag const&)
  666. {
  667. for(; r; ++r)
  668. {
  669. if(pred(*r))
  670. {
  671. return true;
  672. }
  673. }
  674. return false;
  675. }
  676. template< ss_typename_param_k R
  677. , ss_typename_param_k P
  678. >
  679. inline ss_bool_t r_exists_if_1_impl(R r, P pred, iterable_range_tag const&)
  680. {
  681. return std::find_if(r.begin(), r.end(), pred) != r.end();
  682. }
  683. template< ss_typename_param_k R
  684. , ss_typename_param_k P
  685. >
  686. inline ss_bool_t r_exists_if_1_impl(R r, P pred, basic_indirect_range_tag const&)
  687. {
  688. return indirect_range_adaptor<R>(r).exists_if(pred);
  689. }
  690. template< ss_typename_param_k R
  691. , ss_typename_param_k P
  692. >
  693. inline ss_bool_t r_exists_if_1_impl(R r, P pred, indirect_range_tag const&)
  694. {
  695. return r.exists_if(pred);
  696. }
  697. /** \brief Determines whether a value matching the given predicate exists in the range
  698. *
  699. * \ingroup group__library__rangelib
  700. *
  701. * \param r The range
  702. * \param pred The predicate used to match the items
  703. *
  704. * \note: Supports Notional, Iterable and Indirect Range types
  705. */
  706. template< ss_typename_param_k R
  707. , ss_typename_param_k P
  708. >
  709. inline ss_bool_t r_exists_if(R r, P pred)
  710. {
  711. return r_exists_if_1_impl(r, pred, r);
  712. }
  713. /* *********************************************************
  714. * exists_if (2)
  715. */
  716. template< ss_typename_param_k R
  717. , ss_typename_param_k P
  718. , ss_typename_param_k T
  719. >
  720. inline ss_bool_t r_exists_if_2_impl(R r, P pred, T &result, notional_range_tag const&)
  721. {
  722. for(; r; ++r)
  723. {
  724. if(pred(*r))
  725. {
  726. result = *r;
  727. return true;
  728. }
  729. }
  730. return false;
  731. }
  732. template< ss_typename_param_k I
  733. , ss_typename_param_k V
  734. >
  735. inline ss_bool_t r_exists_if_2_impl_helper_(I from, I to, V &val)
  736. {
  737. if(from == to)
  738. {
  739. return false;
  740. }
  741. else
  742. {
  743. val = *from;
  744. return true;
  745. }
  746. }
  747. template< ss_typename_param_k R
  748. , ss_typename_param_k P
  749. , ss_typename_param_k T
  750. >
  751. inline ss_bool_t r_exists_if_2_impl(R r, P pred, T &result, iterable_range_tag const&)
  752. {
  753. return r_exists_if_2_impl_helper_(std::find_if(r.begin(), r.end(), pred), r.end());
  754. }
  755. template< ss_typename_param_k R
  756. , ss_typename_param_k P
  757. , ss_typename_param_k T
  758. >
  759. inline ss_bool_t r_exists_if_2_impl(R r, P pred, T &result, basic_indirect_range_tag const&)
  760. {
  761. return indirect_range_adaptor<R>(r).exists_if(pred, result);
  762. }
  763. template< ss_typename_param_k R
  764. , ss_typename_param_k P
  765. , ss_typename_param_k T
  766. >
  767. inline ss_bool_t r_exists_if_2_impl(R r, P pred, T &result, indirect_range_tag const&)
  768. {
  769. return r.exists_if(pred, result);
  770. }
  771. /** \brief Determines whether a value matching the given predicate exists in the range
  772. *
  773. * \ingroup group__library__rangelib
  774. *
  775. * \param r The range
  776. * \param pred The predicate used to match the items
  777. * \param result The returned result
  778. *
  779. * \note: Supports Notional, Iterable and Indirect Range types
  780. */
  781. template< ss_typename_param_k R
  782. , ss_typename_param_k P
  783. , ss_typename_param_k T
  784. >
  785. inline R r_exists_if(R r, P pred, T &result)
  786. {
  787. return r_exists_if_2_impl(r, pred, result, r);
  788. }
  789. /* *********************************************************
  790. * fill
  791. */
  792. template< ss_typename_param_k R
  793. , ss_typename_param_k T
  794. >
  795. inline void r_fill_impl(R r, T const& val, iterable_range_tag const&)
  796. {
  797. std::fill(r.begin(), r.end(), val);
  798. }
  799. /** \brief Sets the elements in the range to the given value
  800. *
  801. * \ingroup group__library__rangelib
  802. *
  803. * \param r The range
  804. * \param val The value to assign to all elements in the range
  805. *
  806. * \note: Supports Iterable Range type
  807. */
  808. template< ss_typename_param_k R
  809. , ss_typename_param_k T
  810. >
  811. inline void r_fill(R r, T const& val)
  812. {
  813. r_fill_impl(r, val, r);
  814. }
  815. /* *********************************************************
  816. * fill_n
  817. */
  818. template< ss_typename_param_k R
  819. , ss_typename_param_k S
  820. , ss_typename_param_k T
  821. >
  822. inline void r_fill_n_impl(R r, S n, T const& val, iterable_range_tag const&)
  823. {
  824. std::fill(r.begin(), n, val);
  825. }
  826. /** \brief Sets the first \c n elements in the range to the given value
  827. *
  828. * \ingroup group__library__rangelib
  829. *
  830. * \param r The range
  831. * \param n The number of elements to set. This must be <code><= r_distance(r)</code>
  832. * \param val The value to assign to all elements in the range
  833. *
  834. * \note: Supports Iterable Range type
  835. */
  836. template< ss_typename_param_k R
  837. , ss_typename_param_k S
  838. , ss_typename_param_k T
  839. >
  840. inline void r_fill_n(R r, S n, T const& val)
  841. {
  842. STLSOFT_ASSERT(n <= r_distance(r));
  843. r_fill_1_impl(r, n, val, r);
  844. }
  845. /* *********************************************************
  846. * find
  847. */
  848. template< ss_typename_param_k R
  849. , ss_typename_param_k T
  850. >
  851. inline R r_find_impl(R r, T const& val, notional_range_tag const&)
  852. {
  853. for(; r; ++r)
  854. {
  855. if(val == *r)
  856. {
  857. break;
  858. }
  859. }
  860. return r;
  861. }
  862. template< ss_typename_param_k R
  863. , ss_typename_param_k T
  864. >
  865. inline R r_find_impl(R r, T const& val, iterable_range_tag const&)
  866. {
  867. return R(std::find(r.begin(), r.end(), val), r.end());
  868. }
  869. /** \brief Finds the first instance of the given value in the range
  870. *
  871. * \ingroup group__library__rangelib
  872. *
  873. * \param r The range
  874. * \param val The value to find
  875. *
  876. * \note: Supports Notional and Iterable Range types
  877. */
  878. template< ss_typename_param_k R
  879. , ss_typename_param_k T
  880. >
  881. inline R r_find(R r, T const& val)
  882. {
  883. return r_find_impl(r, val, r);
  884. }
  885. /* *********************************************************
  886. * find_if
  887. */
  888. // find_if
  889. template< ss_typename_param_k R
  890. , ss_typename_param_k P
  891. >
  892. inline R r_find_if_impl(R r, P pred, notional_range_tag const&)
  893. {
  894. for(; r; ++r)
  895. {
  896. if(pred(*r))
  897. {
  898. break;
  899. }
  900. }
  901. return r;
  902. }
  903. template< ss_typename_param_k R
  904. , ss_typename_param_k P
  905. >
  906. inline R r_find_if_impl(R r, P pred, iterable_range_tag const&)
  907. {
  908. return R(std::find_if(r.begin(), r.end(), pred), r.end());
  909. }
  910. /** \brief Finds the first instance of a value in the range matching the given predicate
  911. *
  912. * \ingroup group__library__rangelib
  913. *
  914. * \param r The range
  915. * \param pred The value to find
  916. *
  917. * \note: Supports Notional and Iterable Range types
  918. */
  919. template< ss_typename_param_k R
  920. , ss_typename_param_k P
  921. >
  922. inline R r_find_if(R r, P pred)
  923. {
  924. return r_find_if_impl(r, pred, r);
  925. }
  926. /* *********************************************************
  927. * for_each
  928. */
  929. template< ss_typename_param_k R
  930. , ss_typename_param_k F
  931. >
  932. inline F r_for_each_impl(R r, F f, notional_range_tag const&)
  933. {
  934. for(; r; ++r)
  935. {
  936. f(*r);
  937. }
  938. return f;
  939. }
  940. template< ss_typename_param_k R
  941. , ss_typename_param_k F
  942. >
  943. inline F r_for_each_impl(R r, F f, iterable_range_tag const&)
  944. {
  945. return std::for_each(r.begin(), r.end(), f);
  946. }
  947. template< ss_typename_param_k R
  948. , ss_typename_param_k F
  949. >
  950. inline F r_for_each_impl(R r, F f, basic_indirect_range_tag const&)
  951. {
  952. return indirect_range_adaptor<R>(r).for_each(f);
  953. }
  954. template< ss_typename_param_k R
  955. , ss_typename_param_k F
  956. >
  957. inline F r_for_each_impl(R r, F f, indirect_range_tag const&)
  958. {
  959. return r.for_each(f);
  960. }
  961. /** \brief Applies the given function to every element in the range
  962. *
  963. * \ingroup group__library__rangelib
  964. *
  965. * \param r The range
  966. * \param f The function to apply
  967. *
  968. * \note: Supports Notional, Iterable and Indirect Range types
  969. */
  970. template< ss_typename_param_k R
  971. , ss_typename_param_k F
  972. >
  973. inline F r_for_each(R r, F f)
  974. {
  975. return r_for_each_impl(r, f, r);
  976. }
  977. /* *********************************************************
  978. * generate
  979. */
  980. template< ss_typename_param_k R
  981. , ss_typename_param_k F
  982. >
  983. inline void r_generate_impl(R r, F f, iterable_range_tag const&)
  984. {
  985. std::generate(r.begin(), r.end(), f);
  986. }
  987. /** \brief Sets each element in the range to the result of the given function
  988. *
  989. * \ingroup group__library__rangelib
  990. *
  991. * \param r The range
  992. * \param f The generator function
  993. *
  994. * \note: Supports Iterable Range type
  995. */
  996. template< ss_typename_param_k R
  997. , ss_typename_param_k F
  998. >
  999. inline void r_generate(R r, F f)
  1000. {
  1001. r_generate_impl(r, f, r);
  1002. }
  1003. /* *********************************************************
  1004. * max_element (1)
  1005. */
  1006. template <ss_typename_param_k R>
  1007. inline ss_typename_type_ret_k R::value_type r_max_element_1_impl(R r, notional_range_tag const&)
  1008. {
  1009. typedef ss_typename_type_k R::value_type value_type_t;
  1010. value_type_t max_ = value_type_t();
  1011. for(; r; ++r)
  1012. {
  1013. if(max_ < *r)
  1014. {
  1015. max_ = *r;
  1016. }
  1017. }
  1018. return max_;
  1019. }
  1020. template <ss_typename_param_k I>
  1021. inline I r_max_element_1_impl_iterable(I from, I to)
  1022. {
  1023. if(from == to)
  1024. {
  1025. STLSOFT_THROW_X(empty_range_exception("Cannot determine maximum element of empty range"));
  1026. }
  1027. return std::max_element(from, to);
  1028. }
  1029. template <ss_typename_param_k R>
  1030. inline ss_typename_type_ret_k R::value_type r_max_element_1_impl(R r, iterable_range_tag const&)
  1031. {
  1032. return *r_max_element_1_impl_iterable(r.begin(), r.end());
  1033. }
  1034. template <ss_typename_param_k R>
  1035. inline ss_typename_type_ret_k R::value_type r_max_element_1_impl(R r, basic_indirect_range_tag const&)
  1036. {
  1037. return indirect_range_adaptor<R>(r).max_element();
  1038. }
  1039. template <ss_typename_param_k R>
  1040. inline ss_typename_type_ret_k R::value_type r_max_element_1_impl(R r, indirect_range_tag const&)
  1041. {
  1042. return r.max_element();
  1043. }
  1044. /** \brief Evaluates the maximum element in the range
  1045. *
  1046. * \ingroup group__library__rangelib
  1047. *
  1048. * \param r The range. Cannot be closed
  1049. *
  1050. * \note: Supports Notional, Iterable and Indirect Range types
  1051. * \note: The behaviour is undefined if the range is closed
  1052. */
  1053. template <ss_typename_param_k R>
  1054. inline ss_typename_type_ret_k R::value_type r_max_element(R r)
  1055. {
  1056. STLSOFT_ASSERT(r_distance(r) > 0);
  1057. return r_max_element_1_impl(r, r);
  1058. }
  1059. /* *********************************************************
  1060. * max_element (2)
  1061. */
  1062. template< ss_typename_param_k I
  1063. , ss_typename_param_k F
  1064. >
  1065. inline I r_max_element_2_impl_iterable(I from, I to, F f)
  1066. {
  1067. if(from == to)
  1068. {
  1069. STLSOFT_THROW_X(empty_range_exception("Cannot determine maximum element of empty range"));
  1070. }
  1071. return std::max_element(from, to, f);
  1072. }
  1073. template< ss_typename_param_k R
  1074. , ss_typename_param_k F
  1075. >
  1076. inline ss_typename_type_ret_k R::value_type r_max_element_2_impl(R r, F f, iterable_range_tag const&)
  1077. {
  1078. return *r_max_element_2_impl_iterable(r.begin(), r.end(), f);
  1079. }
  1080. template< ss_typename_param_k R
  1081. , ss_typename_param_k F
  1082. >
  1083. inline ss_typename_type_ret_k R::value_type r_max_element_2_impl(R r, F f, notional_range_tag const&)
  1084. {
  1085. typedef ss_typename_type_k R::value_type value_type_t;
  1086. value_type_t max_ = value_type_t();
  1087. for(; r; ++r)
  1088. {
  1089. if(f(max_, *r))
  1090. {
  1091. max_ = *r;
  1092. }
  1093. }
  1094. return max_;
  1095. }
  1096. template< ss_typename_param_k R
  1097. , ss_typename_param_k F
  1098. >
  1099. inline ss_typename_type_ret_k R::value_type r_max_element_2_impl(R r, F f, basic_indirect_range_tag const&)
  1100. {
  1101. return indirect_range_adaptor<R>(r).max_element(f);
  1102. }
  1103. template< ss_typename_param_k R
  1104. , ss_typename_param_k F
  1105. >
  1106. inline ss_typename_type_ret_k R::value_type r_max_element_2_impl(R r, F f, indirect_range_tag const&)
  1107. {
  1108. return r.max_element(f);
  1109. }
  1110. /** \brief Evaluates the maximum element in the range evaluated according to the given function
  1111. *
  1112. * \ingroup group__library__rangelib
  1113. *
  1114. * \param r The range. Cannot be closed
  1115. * \param f The function used to evaluate the ordering
  1116. *
  1117. * \note: Supports Notional, Iterable and Indirect Range types
  1118. * \note: The behaviour is undefined if the range is closed
  1119. */
  1120. template< ss_typename_param_k R
  1121. , ss_typename_param_k F
  1122. >
  1123. inline ss_typename_type_ret_k R::value_type r_max_element(R r, F f)
  1124. {
  1125. STLSOFT_ASSERT(r_distance(r) > 0);
  1126. return r_max_element_2_impl(r, f, r);
  1127. }
  1128. /* *********************************************************
  1129. * min_element (1)
  1130. */
  1131. template <ss_typename_param_k R>
  1132. inline ss_typename_type_ret_k R::value_type r_min_element_1_impl(R r, notional_range_tag const&)
  1133. {
  1134. typedef ss_typename_type_k R::value_type value_type_t;
  1135. if(!r)
  1136. {
  1137. return value_type_t();
  1138. }
  1139. else
  1140. {
  1141. value_type_t min_ = *r;
  1142. for(; ++r; )
  1143. {
  1144. if(*r < min_)
  1145. {
  1146. min_ = *r;
  1147. }
  1148. }
  1149. return min_;
  1150. }
  1151. }
  1152. template <ss_typename_param_k I>
  1153. inline I r_min_element_1_impl_iterable(I from, I to)
  1154. {
  1155. if(from == to)
  1156. {
  1157. STLSOFT_THROW_X(empty_range_exception("Cannot determine minimum element of empty range"));
  1158. }
  1159. return std::min_element(from, to);
  1160. }
  1161. template <ss_typename_param_k R>
  1162. inline ss_typename_type_ret_k R::value_type r_min_element_1_impl(R r, iterable_range_tag const&)
  1163. {
  1164. return *r_min_element_1_impl_iterable(r.begin(), r.end());
  1165. }
  1166. template <ss_typename_param_k R>
  1167. inline ss_typename_type_ret_k R::value_type r_min_element_1_impl(R r, basic_indirect_range_tag const&)
  1168. {
  1169. return indirect_range_adaptor<R>(r).min_element();
  1170. }
  1171. template <ss_typename_param_k R>
  1172. inline ss_typename_type_ret_k R::value_type r_min_element_1_impl(R r, indirect_range_tag const&)
  1173. {
  1174. return r.min_element();
  1175. }
  1176. /** \brief Evaluates the minimum element in the range
  1177. *
  1178. * \ingroup group__library__rangelib
  1179. *
  1180. * \param r The range. Cannot be closed
  1181. *
  1182. * \note: Supports Notional, Iterable and Indirect Range types
  1183. * \note: The behaviour is undefined if the range is closed
  1184. */
  1185. template <ss_typename_param_k R>
  1186. inline ss_typename_type_ret_k R::value_type r_min_element(R r)
  1187. {
  1188. STLSOFT_ASSERT(r_distance(r) > 0);
  1189. return r_min_element_1_impl(r, r);
  1190. }
  1191. /* *********************************************************
  1192. * min_element (2)
  1193. */
  1194. template< ss_typename_param_k I
  1195. , ss_typename_param_k F
  1196. >
  1197. inline I r_min_element_2_impl_iterable(I from, I to, F f)
  1198. {
  1199. if(from == to)
  1200. {
  1201. STLSOFT_THROW_X(empty_range_exception("Cannot determine minimum element of empty range"));
  1202. }
  1203. return std::min_element(from, to, f);
  1204. }
  1205. template< ss_typename_param_k R
  1206. , ss_typename_param_k F
  1207. >
  1208. inline ss_typename_type_ret_k R::value_type r_min_element_2_impl(R r, F f, iterable_range_tag const&)
  1209. {
  1210. return *r_min_element_2_impl_iterable(r.begin(), r.end(), f);
  1211. }
  1212. template< ss_typename_param_k R
  1213. , ss_typename_param_k F
  1214. >
  1215. inline ss_typename_type_ret_k R::value_type r_min_element_2_impl(R r, F f, notional_range_tag const&)
  1216. {
  1217. typedef ss_typename_type_k R::value_type value_type_t;
  1218. value_type_t min_ = value_type_t();
  1219. for(; r; ++r)
  1220. {
  1221. if(f(min_, *r))
  1222. {
  1223. min_ = *r;
  1224. }
  1225. }
  1226. return min_;
  1227. }
  1228. template< ss_typename_param_k R
  1229. , ss_typename_param_k F
  1230. >
  1231. inline ss_typename_type_ret_k R::value_type r_min_element_2_impl(R r, F f, basic_indirect_range_tag const&)
  1232. {
  1233. return indirect_range_adaptor<R>(r).min_element(f);
  1234. }
  1235. template< ss_typename_param_k R
  1236. , ss_typename_param_k F
  1237. >
  1238. inline ss_typename_type_ret_k R::value_type r_min_element_2_impl(R r, F f, indirect_range_tag const&)
  1239. {
  1240. return r.min_element(f);
  1241. }
  1242. /** \brief Evaluates the minimum element in the range evaluated according to the given function
  1243. *
  1244. * \ingroup group__library__rangelib
  1245. *
  1246. * \param r The range. Cannot be closed
  1247. * \param f The function used to evaluate the ordering
  1248. *
  1249. * \note: Supports Notional, Iterable and Indirect Range types
  1250. * \note: The behaviour is undefined if the range is closed
  1251. */
  1252. template< ss_typename_param_k R
  1253. , ss_typename_param_k F
  1254. >
  1255. inline ss_typename_type_ret_k R::value_type r_min_element(R r, F f)
  1256. {
  1257. STLSOFT_ASSERT(r_distance(r) > 0);
  1258. return r_min_element_2_impl(r, f, r);
  1259. }
  1260. /* *********************************************************
  1261. * replace
  1262. */
  1263. template< ss_typename_param_k R
  1264. , ss_typename_param_k T
  1265. >
  1266. inline void r_replace_impl(R r, T oldVal, T newVal, iterable_range_tag const&)
  1267. {
  1268. std::replace(r.begin(), r.end(), oldVal, newVal);
  1269. }
  1270. template< ss_typename_param_k R
  1271. , ss_typename_param_k T
  1272. >
  1273. inline void r_replace_impl(R r, T oldVal, T newVal, indirect_range_tag const&)
  1274. {
  1275. r.replace(r, oldVal, newVal);
  1276. }
  1277. /** \brief Replaces all elements of the given old value with the new value
  1278. *
  1279. * \ingroup group__library__rangelib
  1280. *
  1281. * \param r The range
  1282. * \param oldVal The value to search for
  1283. * \param newVal The value to replace any elements with \c oldVal
  1284. *
  1285. * \note: Supports Iterable and Indirect Range types
  1286. */
  1287. template< ss_typename_param_k R
  1288. , ss_typename_param_k T
  1289. >
  1290. inline void r_replace(R r, T oldVal, T newVal)
  1291. {
  1292. r_replace_impl(r, oldVal, newVal, r);
  1293. }
  1294. /* *********************************************************
  1295. * replace_copy
  1296. */
  1297. #if 0
  1298. template< ss_typename_param_k RI
  1299. , ss_typename_param_k RO
  1300. , ss_typename_param_k T
  1301. >
  1302. inline void r_replace_copy_impl(RI ri, RO ro, T oldVal, T newVal, iterable_range_tag const&, iterable_range_tag const&)
  1303. {
  1304. std::replace_copy(ri.begin(), ri.end(), ro.begin(), oldVal, newVal);
  1305. }
  1306. template< ss_typename_param_k RI
  1307. , ss_typename_param_k RO
  1308. , ss_typename_param_k T
  1309. >
  1310. inline void r_replace_copy_impl(RI ri, RO ro, T oldVal, T newVal, indirect_range_tag const&, indirect_range_tag const&)
  1311. {
  1312. ri.replace_copy(ro, oldVal, newVal);
  1313. }
  1314. /** \brief Replaces all elements of the given old value with the new value
  1315. *
  1316. * \ingroup group__library__rangelib
  1317. *
  1318. * \param r The range
  1319. * \param oldVal The value to search for
  1320. * \param newVal The value to replace any elements with \c oldVal
  1321. *
  1322. * \note: Supports Iterable and Indirect Range types
  1323. */
  1324. template< ss_typename_param_k RI
  1325. , ss_typename_param_k RO
  1326. , ss_typename_param_k T
  1327. >
  1328. inline void r_replace_copy(RI ri, RO ro, T oldVal, T newVal)
  1329. {
  1330. r_replace_copy_impl(ri, ro, oldVal, newVal, ri, ro);
  1331. }
  1332. #endif /* 0 */
  1333. /* *********************************************************
  1334. * replace_if
  1335. */
  1336. template< ss_typename_param_k R
  1337. , ss_typename_param_k P
  1338. , ss_typename_param_k T
  1339. >
  1340. inline void r_replace_if_impl(R r, P pred, T newVal, iterable_range_tag const&)
  1341. {
  1342. std::replace_if(r.begin(), r.end(), pred, newVal);
  1343. }
  1344. template< ss_typename_param_k R
  1345. , ss_typename_param_k P
  1346. , ss_typename_param_k T
  1347. >
  1348. inline void r_replace_if_impl(R r, P pred, T newVal, indirect_range_tag const&)
  1349. {
  1350. r.replace_if(r, pred, newVal);
  1351. }
  1352. /** \brief Replaces all elements matching the given predicate with the new value
  1353. *
  1354. * \ingroup group__library__rangelib
  1355. *
  1356. * \param r The range
  1357. * \param pred The predicate for matching the old values to replace
  1358. * \param newVal The value to replace any elements which match the given predicate
  1359. *
  1360. * \note: Supports Iterable and Indirect Range types
  1361. */
  1362. template< ss_typename_param_k R
  1363. , ss_typename_param_k P
  1364. , ss_typename_param_k T
  1365. >
  1366. inline void r_replace_if(R r, P pred, T newVal)
  1367. {
  1368. r_replace_if_impl(r, pred, newVal, r);
  1369. }
  1370. /* *********************************************************
  1371. * replace_copy_if
  1372. */
  1373. #if 0
  1374. template< ss_typename_param_k RI
  1375. , ss_typename_param_k RO
  1376. , ss_typename_param_k P
  1377. , ss_typename_param_k T
  1378. >
  1379. inline void r_replace_copy_if_impl(RI ri, RO ro, P pred, T newVal, iterable_range_tag const&, iterable_range_tag const&)
  1380. {
  1381. std::replace_copy_if(ri.begin(), ri.end(), ro.begin(), pred, newVal);
  1382. }
  1383. template< ss_typename_param_k RI
  1384. , ss_typename_param_k RO
  1385. , ss_typename_param_k P
  1386. , ss_typename_param_k T
  1387. >
  1388. inline void r_replace_copy_if_impl(RI ri, RO ro, P pred, T newVal, notional_range_tag const&, notional_range_tag const&)
  1389. {
  1390. for(; ri; ++ri, ++ro)
  1391. {
  1392. STLSOFT_ASSERT(!(!ro));
  1393. if(pred(*ri))
  1394. {
  1395. *ro = newVal;
  1396. }
  1397. }
  1398. }
  1399. template< ss_typename_param_k RI
  1400. , ss_typename_param_k RO
  1401. , ss_typename_param_k P
  1402. , ss_typename_param_k T
  1403. >
  1404. inline void r_replace_copy_if_impl(RI ri, RO ro, P pred, T newVal, indirect_range_tag const&, indirect_range_tag const&)
  1405. {
  1406. ri.replace_copy_if(ro, pred, newVal);
  1407. }
  1408. template< ss_typename_param_k RI
  1409. , ss_typename_param_k RO
  1410. , ss_typename_param_k P
  1411. , ss_typename_param_k T
  1412. >
  1413. inline void r_replace_copy_if(RI ri, RO ro, P pred, T newVal)
  1414. {
  1415. r_replace_copy_if_impl(ri, ro, pe, newVal, ri, ro);
  1416. }
  1417. #endif /* 0 */
  1418. ////////////////////////////////////////////////////////////////////////////
  1419. // Unit-testing
  1420. #ifdef STLSOFT_UNITTEST
  1421. # include "./unittest/algorithms_unittest_.h"
  1422. #endif /* STLSOFT_UNITTEST */
  1423. /* ////////////////////////////////////////////////////////////////////// */
  1424. #ifndef RANGELIB_NO_NAMESPACE
  1425. # if defined(_STLSOFT_NO_NAMESPACE) || \
  1426. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  1427. } // namespace rangelib
  1428. # else
  1429. } // namespace rangelib_project
  1430. } // namespace stlsoft
  1431. # endif /* _STLSOFT_NO_NAMESPACE */
  1432. #endif /* !RANGELIB_NO_NAMESPACE */
  1433. /* ////////////////////////////////////////////////////////////////////// */
  1434. #endif /* !RANGELIB_INCL_RANGELIB_HPP_ALGORITHMS */
  1435. /* ///////////////////////////// end of file //////////////////////////// */