On 23/08/16 11:19 +0100, Jonathan Wakely wrote:
As Casey pointed out, our operator- overloads for reverse_iterator and
move_iterator are not conforming. For reverse_iterator the overload
taking a single template argument is not SFINAE friendly, and for
move_iterator it enables some expressions that aren't supposed to be
valid.
This removes the problematic operator- overloads for C++11 and later.
Anyone writing a greedy operator- in their own namespace should
constrain it to be less greedy.
(This matches what libc++ implements, and they don't seem to have a
problem with it).
Because the synopsis of <iterator> is so different in each standard
I've added multiple testcases for it.
PR libstdc++/71771
* include/bits/stl_iterator.h
(operator-(reverse_iterator<Iter>, reverse_iterator<Iter>): Only
define for C++98 mode.
(operator-(move_iterator<Iter>, move_iterator<Iter>): Don't define.
* testsuite/24_iterators/headers/iterator/synopsis.cc: Use
-std=gnu++98.
* testsuite/24_iterators/headers/iterator/synopsis_c++11.cc: New test.
* testsuite/24_iterators/headers/iterator/synopsis_c++14.cc: New test.
* testsuite/24_iterators/headers/iterator/synopsis_c++17.cc: New test.
* testsuite/24_iterators/move_iterator/greedy_ops.cc: Don't test
difference operator.
* testsuite/24_iterators/reverse_iterator/greedy_ops.cc: Only test
difference operator for C++98.
* testsuite/24_iterators/reverse_iterator/71771.cc: New test.
Tested powerpc64le-linux, committed to trunk.
For gcc-5 and gcc-6 I'm making this smaller change that retains the
non-standard overload, but constrains it so it's SFINAE-friendly.
Tested x86_64-linux, committed to gcc-5-branch and gcc-6-branch.
commit 115a595a7a47462333bf0127c45b903e0ce0aca2
Author: Jonathan Wakely <jwak...@redhat.com>
Date: Tue Aug 23 00:59:42 2016 +0100
libstdc++/71771 constrain reverse_iterator difference op
* include/bits/stl_iterator.h
(operator-(reverse_iterator<Iter>, reverse_iterator<Iter>): Constrain
for C++11 and later.
* testsuite/24_iterators/reverse_iterator/71771.cc: New test.
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 3401cd0..17e6ff0 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -324,9 +324,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return !(__x < __y); }
template<typename _Iterator>
+#if __cplusplus < 201103L
inline typename reverse_iterator<_Iterator>::difference_type
operator-(const reverse_iterator<_Iterator>& __x,
const reverse_iterator<_Iterator>& __y)
+#else
+ inline auto
+ operator-(const reverse_iterator<_Iterator>& __x,
+ const reverse_iterator<_Iterator>& __y)
+ -> decltype(__x.base() - __y.base())
+#endif
{ return __y.base() - __x.base(); }
template<typename _Iterator>
diff --git a/libstdc++-v3/testsuite/24_iterators/reverse_iterator/71771.cc b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/71771.cc
new file mode 100644
index 0000000..1a7c963
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/71771.cc
@@ -0,0 +1,43 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++11 } }
+
+#include <iterator>
+#include <testsuite_iterators.h>
+
+// PR libstdc++/71771
+
+template<typename Iter>
+auto
+diff2(std::reverse_iterator<Iter> it1, std::reverse_iterator<Iter> it2)
+-> decltype(it1 - it2)
+{ return it1 - it2; }
+
+template<typename Iter>
+void
+diff2(Iter, Iter)
+{ }
+
+void
+test01()
+{
+ int i[2];
+ __gnu_test::test_container<int, __gnu_test::bidirectional_iterator_wrapper>
+ c(i);
+ diff2(std::rbegin(c), std::rend(c));
+}