This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [patch] C++14: N3671 Making non-modifying sequence operations more robust
- From: Chris Jefferson <chris at bubblescope dot net>
- To: libstdc++ at gcc dot gnu dot org
- Date: Mon, 10 Jun 2013 23:08:44 +0100
- Subject: Re: [patch] C++14: N3671 Making non-modifying sequence operations more robust
- References: <CAH6eHdQWhZjPJczqLT+jYs16RuokiqezVJcia_5up6e1KbevBg at mail dot gmail dot com>
On 08/06/13 17:13, Jonathan Wakely wrote:
Another C++14 feature.
* include/bits/stl_algo.h (is_permutation): Add overloads from N3671.
* include/bits/stl_algobase.h (equal, mismatch): Likewise.
* testsuite/25_algorithms/equal/1.cc: Remove duplicate test case.
* testsuite/25_algorithms/equal/2.cc: New.
* testsuite/25_algorithms/equal/check_type2.cc: New.
* testsuite/25_algorithms/is_permutationqual/2.cc: New.
* testsuite/25_algorithms/is_permutationqual/check_type2.cc: New.
* testsuite/25_algorithms/mismatch/2.cc: New.
* testsuite/25_algorithms/mismatch/check_type2.cc: New.
* testsuite/util/testsuite_iterators.h: Fix spelling.
Tested x86_64-linux, committed to trunk.
Small tweak, in (for example):
+ template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
+ inline bool
+ equal(_IIter1 __first1, _IIter1 __last1,
+ _IIter2 __first2, _IIter2 __last2, _BinaryPredicate __binary_pred)
+ {
+ // concept requirements
+ __glibcxx_function_requires(_InputIteratorConcept<_IIter1>)
+ __glibcxx_function_requires(_InputIteratorConcept<_IIter2>)
+ __glibcxx_requires_valid_range(__first1, __last1);
+ __glibcxx_requires_valid_range(__first2, __last2);
+
+ using _Cat1 = typename iterator_traits<_IIter1>::iterator_category;
+ using _Cat2 = typename iterator_traits<_IIter2>::iterator_category;
+ using _IIter1_is_RA = is_same<_Cat1, random_access_iterator_tag>;
+ using _IIter2_is_RA = is_same<_Cat2, random_access_iterator_tag>;
+ constexpr bool __ra_iters = _IIter1_is_RA() && _IIter1_is_RA();
+ if (__ra_iters)
+ {
+ auto __d1 = std::distance(__first1, __last1);
+ auto __d2 = std::distance(__first2, __last2);
+ if (__d1 != __d2)
+ return false;
+ }
+
+ for (; __first1 != __last1 && __first2 != __last2; ++__first1,
++__first2)
+ if (!bool(__binary_pred(*__first1, *__first2)))
+ return false;
+ return __ra_iters || (__first1 == __last1 && __first2 == __last2);
+ }
After we are in the 'if(__ra_iters)' case, and checked that __d1==__d2,
could dispatch to old-fashioned equal(__first1, __last1, __first2,
__binary_pred). This has the advantage that it saves repeatedly checking
__first2 != __last2 unnessasairly, and I suspect only having one loop
condition to check will give the compiler a better shot at optimising /
unrolling (although, I haven't checked that I will admit).
Chris