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 <fdum...@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.