This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] C++14: N3671 Making non-modifying sequence operations more robust


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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]