[libcxx-commits] [libcxx] e4d3a99 - [libc++] Implement LWG3435 (constraints on reverse_iterator and move_iterator)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jun 3 12:50:07 PDT 2021
Author: Louis Dionne
Date: 2021-06-03T15:49:41-04:00
New Revision: e4d3a993c2675f46cbe99acd1bf6e6d39d9c1aee
URL: https://github.com/llvm/llvm-project/commit/e4d3a993c2675f46cbe99acd1bf6e6d39d9c1aee
DIFF: https://github.com/llvm/llvm-project/commit/e4d3a993c2675f46cbe99acd1bf6e6d39d9c1aee.diff
LOG: [libc++] Implement LWG3435 (constraints on reverse_iterator and move_iterator)
Added:
libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.convert.LWG3435.verify.cpp
libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.iter.explicit.verify.cpp
libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/assign.LWG3435.verify.cpp
libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.LWG3435.verify.cpp
libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp
Modified:
libcxx/docs/Cxx2bStatusIssuesStatus.csv
libcxx/include/iterator
libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.pass.cpp
Removed:
libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/convert.compile.fail.cpp
libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/iter.compile.fail.cpp
libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.compile.fail.cpp
################################################################################
diff --git a/libcxx/docs/Cxx2bStatusIssuesStatus.csv b/libcxx/docs/Cxx2bStatusIssuesStatus.csv
index 2e4f416e9ecff..15356409a0356 100644
--- a/libcxx/docs/Cxx2bStatusIssuesStatus.csv
+++ b/libcxx/docs/Cxx2bStatusIssuesStatus.csv
@@ -6,7 +6,7 @@
"`3211 <https://wg21.link/LWG3211>`__","``std::tuple<>`` should be trivially constructible","November 2020","",""
"`3236 <https://wg21.link/LWG3236>`__","Random access iterator requirements lack limiting relational operators domain to comparing those from the same range","November 2020","",""
"`3265 <https://wg21.link/LWG3265>`__","``move_iterator``'s conversions are more broken after P1207","November 2020","Fixed by `LWG3435 <https://wg21.link/LWG3435>`__",""
-"`3435 <https://wg21.link/LWG3435>`__","``three_way_comparable_with<reverse_iterator<int*>, reverse_iterator<const int*>>``","November 2020","",""
+"`3435 <https://wg21.link/LWG3435>`__","``three_way_comparable_with<reverse_iterator<int*>, reverse_iterator<const int*>>``","November 2020","|Complete|","13.0"
"`3432 <https://wg21.link/LWG3432>`__","Missing requirement for comparison_category","November 2020","",""
"`3447 <https://wg21.link/LWG3447>`__","Deduction guides for ``take_view`` and ``drop_view`` have
diff erent constraints","November 2020","",""
"`3450 <https://wg21.link/LWG3450>`__","The const overloads of ``take_while_view::begin/end`` are underconstrained","November 2020","",""
diff --git a/libcxx/include/iterator b/libcxx/include/iterator
index 9d9a5532a2c63..06617146da8f8 100644
--- a/libcxx/include/iterator
+++ b/libcxx/include/iterator
@@ -669,27 +669,53 @@ public:
#ifndef _LIBCPP_ABI_NO_ITERATOR_BASES
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reverse_iterator() : __t(), current() {}
+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
explicit reverse_iterator(_Iter __x) : __t(__x), current(__x) {}
- template <class _Up>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
- reverse_iterator(const reverse_iterator<_Up>& __u) : __t(__u.base()), current(__u.base()) {}
- template <class _Up>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
- reverse_iterator& operator=(const reverse_iterator<_Up>& __u)
- { __t = current = __u.base(); return *this; }
+
+ template <class _Up, class = _EnableIf<
+ !is_same<_Up, _Iter>::value && is_convertible<_Up const&, _Iter>::value
+ > >
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+ reverse_iterator(const reverse_iterator<_Up>& __u)
+ : __t(__u.base()), current(__u.base())
+ { }
+
+ template <class _Up, class = _EnableIf<
+ !is_same<_Up, _Iter>::value &&
+ is_convertible<_Up const&, _Iter>::value &&
+ is_assignable<_Up const&, _Iter>::value
+ > >
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+ reverse_iterator& operator=(const reverse_iterator<_Up>& __u) {
+ __t = current = __u.base();
+ return *this;
+ }
#else
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reverse_iterator() : current() {}
+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
explicit reverse_iterator(_Iter __x) : current(__x) {}
- template <class _Up>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
- reverse_iterator(const reverse_iterator<_Up>& __u) : current(__u.base()) {}
- template <class _Up>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
- reverse_iterator& operator=(const reverse_iterator<_Up>& __u)
- { current = __u.base(); return *this; }
+
+ template <class _Up, class = _EnableIf<
+ !is_same<_Up, _Iter>::value && is_convertible<_Up const&, _Iter>::value
+ > >
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+ reverse_iterator(const reverse_iterator<_Up>& __u)
+ : current(__u.base())
+ { }
+
+ template <class _Up, class = _EnableIf<
+ !is_same<_Up, _Iter>::value &&
+ is_convertible<_Up const&, _Iter>::value &&
+ is_assignable<_Up const&, _Iter>::value
+ > >
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+ reverse_iterator& operator=(const reverse_iterator<_Up>& __u) {
+ current = __u.base();
+ return *this;
+ }
#endif
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
_Iter base() const {return current;}
@@ -1217,11 +1243,27 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
move_iterator() : __i() {}
+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
explicit move_iterator(_Iter __x) : __i(__x) {}
- template <class _Up>
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
- move_iterator(const move_iterator<_Up>& __u) : __i(__u.base()) {}
+
+ template <class _Up, class = _EnableIf<
+ !is_same<_Up, _Iter>::value && is_convertible<_Up const&, _Iter>::value
+ > >
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+ move_iterator(const move_iterator<_Up>& __u) : __i(__u.base()) {}
+
+ template <class _Up, class = _EnableIf<
+ !is_same<_Up, _Iter>::value &&
+ is_convertible<_Up const&, _Iter>::value &&
+ is_assignable<_Iter&, _Up const&>::value
+ > >
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+ move_iterator& operator=(const move_iterator<_Up>& __u) {
+ __i = __u.base();
+ return *this;
+ }
+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter base() const {return __i;}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reference operator*() const { return static_cast<reference>(*__i); }
diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/convert.compile.fail.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.convert.LWG3435.verify.cpp
similarity index 50%
rename from libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/convert.compile.fail.cpp
rename to libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.convert.LWG3435.verify.cpp
index 4e60adc689f09..7ef5655b26706 100644
--- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/convert.compile.fail.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.convert.LWG3435.verify.cpp
@@ -6,37 +6,20 @@
//
//===----------------------------------------------------------------------===//
-// GCC 5 does not evaluate static assertions dependent on a template parameter.
-// UNSUPPORTED: gcc-5
-
// <iterator>
// move_iterator
// template <class U>
-// requires HasConstructor<Iter, const U&>
-// move_iterator(const move_iterator<U> &u);
-
-// test requires
+// requires !same_as<U, Iter> && convertible_to<const U&, Iter>
+// move_iterator(const move_iterator<U> &u);
#include <iterator>
-template <class It, class U>
-void
-test(U u)
-{
- std::move_iterator<U> r2(u);
- std::move_iterator<It> r1 = r2;
-}
-
-struct base {};
-struct derived {};
-
-int main(int, char**)
-{
- derived d;
-
- test<base*>(&d);
+struct Base { };
+struct Derived : Base { };
- return 0;
+void test() {
+ std::move_iterator<Base*> base;
+ std::move_iterator<Derived*> derived(base); // expected-error {{no matching constructor for initialization of 'std::move_iterator<Derived *>'}}
}
diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/iter.compile.fail.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.iter.explicit.verify.cpp
similarity index 63%
rename from libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/iter.compile.fail.cpp
rename to libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.iter.explicit.verify.cpp
index 1dd9813d78608..b14111555966e 100644
--- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/iter.compile.fail.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.iter.explicit.verify.cpp
@@ -6,30 +6,18 @@
//
//===----------------------------------------------------------------------===//
-// GCC 5 does not evaluate static assertions dependent on a template parameter.
-// UNSUPPORTED: gcc-5
-
// <iterator>
// move_iterator
// explicit move_iterator(Iter );
-// test explicit
+// test explicitness
#include <iterator>
-template <class It>
-void
-test(It i)
-{
- std::move_iterator<It> r = i;
-}
-
-int main(int, char**)
-{
- char s[] = "123";
- test(s);
-
- return 0;
+int main(int, char**) {
+ char const* it = "";
+ std::move_iterator<char const*> r = it; // expected-error{{no viable conversion from 'const char *' to 'std::move_iterator<const char *>'}}
+ return 0;
}
diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/assign.LWG3435.verify.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/assign.LWG3435.verify.cpp
new file mode 100644
index 0000000000000..2bdfadf02decc
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/assign.LWG3435.verify.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <iterator>
+
+// move_iterator
+
+// template <class U>
+// requires !same_as<U, Iter> && convertible_to<const U&, Iter> && assignable_from<Iter&, const U&>
+// move_iterator& operator=(const move_iterator<U>& u);
+
+#include <iterator>
+
+struct Base { };
+struct Derived : Base { };
+
+void test() {
+ std::move_iterator<Base*> base;
+ std::move_iterator<Derived*> derived;
+ derived = base; // expected-error {{no viable overloaded '='}}
+}
diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.compile.fail.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.compile.fail.cpp
deleted file mode 100644
index fafe70647b667..0000000000000
--- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.compile.fail.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// GCC 5 does not evaluate static assertions dependent on a template parameter.
-// UNSUPPORTED: gcc-5
-
-// <iterator>
-
-// move_iterator
-
-// template <class U>
-// requires HasAssign<Iter, const U&>
-// move_iterator&
-// operator=(const move_iterator<U>& u);
-
-// test requires
-
-#include <iterator>
-
-template <class It, class U>
-void
-test(U u)
-{
- const std::move_iterator<U> r2(u);
- std::move_iterator<It> r1;
- r1 = r2;
-}
-
-struct base {};
-struct derived {};
-
-int main(int, char**)
-{
- derived d;
- test<base*>(&d);
-
- return 0;
-}
diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.pass.cpp
index a847192ef6005..9b5441431aa68 100644
--- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.pass.cpp
@@ -29,7 +29,7 @@ test(U u)
{
const std::move_iterator<U> r2(u);
std::move_iterator<It> r1;
- std::move_iterator<It>& rr = r1 = r2;
+ std::move_iterator<It>& rr = (r1 = r2);
assert(r1.base() == u);
assert(&rr == &r1);
}
diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.LWG3435.verify.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.LWG3435.verify.cpp
new file mode 100644
index 0000000000000..3b3c7cb671457
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.LWG3435.verify.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <iterator>
+
+// reverse_iterator
+
+// template <class U>
+// requires !same_as<U, Iter> && convertible_to<const U&, Iter> && assignable_from<Iter&, const U&>
+// reverse_iterator& operator=(const reverse_iterator<U>& u);
+
+#include <iterator>
+
+struct Base { };
+struct Derived : Base { };
+
+void test() {
+ std::reverse_iterator<Base*> base;
+ std::reverse_iterator<Derived*> derived;
+ derived = base; // expected-error {{no viable overloaded '='}}
+}
diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp
new file mode 100644
index 0000000000000..6082809b7b1bd
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <iterator>
+
+// reverse_iterator
+
+// template <class U>
+// requires !same_as<U, Iter> && convertible_to<const U&, Iter>
+// reverse_iterator(const reverse_iterator<U> &);
+
+#include <iterator>
+
+struct Base { };
+struct Derived : Base { };
+
+void test() {
+ std::reverse_iterator<Base*> base;
+ std::reverse_iterator<Derived*> derived(base); // expected-error {{no matching constructor for initialization of 'std::reverse_iterator<Derived *>'}}
+}
More information about the libcxx-commits
mailing list