Fix LWG issue #2106: move_iterators returning prvalues
llvm-svn: 267091
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 906c50859b0d75725850b770f87b71b9d541ecd4
diff --git a/include/iterator b/include/iterator
index e6f4723..0e60aa9 100644
--- a/include/iterator
+++ b/include/iterator
@@ -951,7 +951,12 @@
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
diff --git a/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp b/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp
index 1a3081f..a6d4d61 100644
--- a/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp
+++ b/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp
@@ -26,8 +26,18 @@
#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 @@
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 @@
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
}
diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html
index 81d13e4..23824e4 100644
--- a/www/cxx1z_status.html
+++ b/www/cxx1z_status.html
@@ -114,7 +114,7 @@
<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>