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: Jonathan Wakely <jwakely dot gcc at gmail dot com>
- To: Chris Jefferson <chris at bubblescope dot net>
- Cc: "libstdc++" <libstdc++ at gcc dot gnu dot org>
- Date: Tue, 11 Jun 2013 00:11:01 +0100
- Subject: Re: [patch] C++14: N3671 Making non-modifying sequence operations more robust
- References: <CAH6eHdQWhZjPJczqLT+jYs16RuokiqezVJcia_5up6e1KbevBg at mail dot gmail dot com> <51B64E6C dot 4080408 at bubblescope dot net>
On 10 June 2013 23:08, Chris Jefferson wrote:
> 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).
Good idea, thanks, I'll make that change too.