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: [Bug libstdc++/63500] [4.9/5 Regression] bug in debug version of std::make_move_iterator?


On 14/10/14 23:51 +0200, François Dumont wrote:
Hi

Here is a proposal to fix the issue with iterators which do not expose lvalue references when dereferenced. I simply chose to detect such an issue in c++11 mode thanks to the is_lvalue_reference meta function.

2014-10-15  François Dumont  <fdumont@gcc.gnu.org>

   PR libstdc++/63500
   * include/bits/cpp_type_traits.h (__true_type): Add __value constant.
   (__false_type): Likewise.
   * include/debug/functions.h (__foreign_iterator_aux2): Do not check for
   foreign iterators if input iterators returns rvalue reference.
   * testsuite/23_containers/vector/63500.cc: New.

Tested under Linux x86_64.

François


Index: include/bits/cpp_type_traits.h
===================================================================
--- include/bits/cpp_type_traits.h	(revision 216158)
+++ include/bits/cpp_type_traits.h	(working copy)
@@ -79,9 +79,12 @@
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

-  struct __true_type { };
-  struct __false_type { };
+  struct __true_type
+  { enum { __value = 1 }; };

+  struct __false_type
+  { enum { __value = 0 }; };
+
  template<bool>
    struct __truth_type
    { typedef __false_type __type; };

This change isn't necessary with my suggestion below.

Index: include/debug/functions.h
===================================================================
--- include/debug/functions.h	(revision 216158)
+++ include/debug/functions.h	(working copy)
@@ -34,7 +34,7 @@
					  // _Iter_base
#include <bits/cpp_type_traits.h>	  // for __is_integer
#include <bits/move.h>                    // for __addressof and addressof
-# include <bits/stl_function.h>		  // for less
+#include <bits/stl_function.h>		  // for less
#if __cplusplus >= 201103L
# include <type_traits>			  // for is_lvalue_reference and __and_
#endif
@@ -252,8 +252,21 @@
			    const _InputIterator& __other,
			    const _InputIterator& __other_end)
    {
+#if __cplusplus >= 201103L
+      typedef std::iterator_traits<_InputIterator> _InputIteTraits;
+      typedef typename _InputIteTraits::reference _InputIteRefType;
+#endif
      return __foreign_iterator_aux3(__it, __other, __other_end,
+#if __cplusplus < 201103L
				     _Is_contiguous_sequence<_Sequence>());
+#else
+      typename std::conditional<
+	std::__and_<std::integral_constant<
+	  bool, _Is_contiguous_sequence<_Sequence>::__value>,
+		    std::is_lvalue_reference<_InputIteRefType> >::value,
+	std::__true_type,
+	std::__false_type>::type());
+#endif
    }

I find this much easier to read:

#if __cplusplus < 201103L
     typedef _Is_contiguous_sequence<_Sequence> __tag;
#else
     using __lvalref = std::is_lvalue_reference<
       typename std::iterator_traits<_InputIterator>::reference>;
     using __contiguous = _Is_contiguous_sequence<_Sequence>;
     using __tag = typename std::conditional<__lvalref::value, __contiguous,
                                             std::__false_type>::type;
#endif
     return __foreign_iterator_aux3(__it, __other, __other_end, __tag());

It only has one preprocessor condition and it avoids mismatched
parentheses caused by opening the function parameter list once but
closing it twice in two different branches.


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