Fix LWG issue #2106: move_iterators returning prvalues
authorEric Fiselier <eric@efcs.ca>
Fri, 22 Apr 2016 00:49:12 +0000 (00:49 +0000)
committerEric Fiselier <eric@efcs.ca>
Fri, 22 Apr 2016 00:49:12 +0000 (00:49 +0000)
llvm-svn: 267091

libcxx/include/iterator
libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp
libcxx/www/cxx1z_status.html

index e6f4723..0e60aa9 100644 (file)
@@ -951,7 +951,12 @@ public:
     typedef typename iterator_traits<iterator_type>::difference_type difference_type;
     typedef iterator_type pointer;
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    typedef value_type&& reference;
+    typedef typename iterator_traits<iterator_type>::reference __reference;
+    typedef typename conditional<
+            is_reference<__reference>::value,
+            typename remove_reference<__reference>::type&&,
+            __reference
+        >::type reference;
 #else
     typedef typename iterator_traits<iterator_type>::reference reference;
 #endif
index 1a3081f..a6d4d61 100644 (file)
 #include <iterator>
 #include <type_traits>
 
+#include "test_macros.h"
 #include "test_iterators.h"
 
+template <class ValueType, class Reference>
+struct DummyIt {
+  typedef std::forward_iterator_tag iterator_category;
+  typedef ValueType value_type;
+  typedef std::ptrdiff_t difference_type;
+  typedef ValueType* pointer;
+  typedef Reference reference;
+};
+
 template <class It>
 void
 test()
@@ -38,7 +48,7 @@ test()
     static_assert((std::is_same<typename R::difference_type, typename T::difference_type>::value), "");
     static_assert((std::is_same<typename R::pointer, It>::value), "");
     static_assert((std::is_same<typename R::value_type, typename T::value_type>::value), "");
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#if TEST_STD_VER >= 11
     static_assert((std::is_same<typename R::reference, typename R::value_type&&>::value), "");
 #else
     static_assert((std::is_same<typename R::reference, typename T::reference>::value), "");
@@ -53,4 +63,33 @@ int main()
     test<bidirectional_iterator<char*> >();
     test<random_access_iterator<char*> >();
     test<char*>();
+#if TEST_STD_VER >= 11
+    {
+        typedef DummyIt<int, int> T;
+        typedef std::move_iterator<T> It;
+        static_assert(std::is_same<It::reference, int>::value, "");
+    }
+    {
+        typedef DummyIt<int, std::reference_wrapper<int> > T;
+        typedef std::move_iterator<T> It;
+        static_assert(std::is_same<It::reference, std::reference_wrapper<int> >::value, "");
+    }
+    {
+        // Check that move_iterator uses whatever reference type it's given
+        // when it's not a reference.
+        typedef DummyIt<int, long > T;
+        typedef std::move_iterator<T> It;
+        static_assert(std::is_same<It::reference, long>::value, "");
+    }
+    {
+        typedef DummyIt<int, int&> T;
+        typedef std::move_iterator<T> It;
+        static_assert(std::is_same<It::reference, int&&>::value, "");
+    }
+    {
+        typedef DummyIt<int, int&&> T;
+        typedef std::move_iterator<T> It;
+        static_assert(std::is_same<It::reference, int&&>::value, "");
+    }
+#endif
 }
index 81d13e4..23824e4 100644 (file)
        <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2404">2404</a></td><td><code>mismatch()</code>'s complexity needs to be updated</td><td>Urbana</td><td>Complete</td></tr>
        <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2408">2408</a></td><td>SFINAE-friendly <code>common_type</code> / <code>iterator_traits</code> is missing in C++14</td><td>Urbana</td><td><code>common_type</code> is waiting on <a href="http://cplusplus.github.io/LWG/lwg-defects.html#2465">LWG#2465</a></td></tr>
        <tr><td></td><td></td><td></td><td></td></tr>
-       <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2106">2106</td><td><code>move_iterator</code> wrapping iterators returning prvalues</td><td>Urbana</td><td></td></tr>
+       <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2106">2106</td><td><code>move_iterator</code> wrapping iterators returning prvalues</td><td>Urbana</td><td>Complete</td></tr>
        <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2129">2129</td><td>User specializations of <code>std::initializer_list</code></td><td>Urbana</td><td>Complete</td></tr>
        <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2212">2212</td><td><code>tuple_size</code> for <code>const pair</code> request <tuple> header</td><td>Urbana</td><td>Complete</td></tr>
        <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2217">2217</td><td><code>operator==(sub_match, string)</code> slices on embedded '\0's</td><td>Urbana</td><td>Complete</td></tr>