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));
+}

Reply via email to