diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -68,6 +68,14 @@ template concept indirectly_writable = see below; // since C++20 +// [iterator.concept.winc], concept weakly_­incrementable +template + concept weakly_incrementable = see below; // since C++20 + +// [iterator.concept.inc], concept incrementable +template + concept incrementable = see below; // since C++20 + template struct iterator @@ -2544,6 +2552,32 @@ const_cast&&>(*_VSTD::forward<_Out>(__o)) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving }; +// [iterator.concept.winc] +template +inline constexpr bool __is_signed_integer_like = signed_integral<_Tp>; + +template +concept weakly_incrementable = + default_initializable<_Ip> && + movable<_Ip> && + requires(_Ip __i) { + typename iter_difference_t<_Ip>; + requires __is_signed_integer_like>; + { ++__i } -> same_as<_Ip&>; // not required to be equality-preserving + __i++; // not required to be equality-preserving + }; + +// [iterator.concept.inc] +template +concept incrementable = + regular<_Ip> && + weakly_incrementable<_Ip> && + requires(_Ip __i) { + { __i++ } -> same_as<_Ip>; + }; + +// [iterator.concept.inc] + #undef _LIBCPP_NOEXCEPT_RETURN #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/incrementable.h b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/incrementable.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/incrementable.h @@ -0,0 +1,195 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#ifndef LIBCPP_TEST_STD_ITERATORS_ITERATOR_REQUIREMENTS_ITERATOR_CONCEPTS_INCREMENTABLE_H +#define LIBCPP_TEST_STD_ITERATORS_ITERATOR_REQUIREMENTS_ITERATOR_CONCEPTS_INCREMENTABLE_H + +struct postfix_increment_returns_void { + using difference_type = int; + postfix_increment_returns_void& operator++(); + void operator++(int); +}; + +struct postfix_increment_returns_copy { + using difference_type = int; + postfix_increment_returns_copy& operator++(); + postfix_increment_returns_copy operator++(int); +}; + +struct has_integral_minus { + has_integral_minus& operator++(); + has_integral_minus operator++(int); + + long operator-(has_integral_minus) const; +}; + +struct has_distinct_difference_type_and_minus { + using difference_type = short; + + has_distinct_difference_type_and_minus& operator++(); + has_distinct_difference_type_and_minus operator++(int); + + long operator-(has_distinct_difference_type_and_minus) const; +}; + +struct missing_difference_type { + missing_difference_type& operator++(); + void operator++(int); +}; + +struct floating_difference_type { + using difference_type = float; + + floating_difference_type& operator++(); + void operator++(int); +}; + +struct non_const_minus { + non_const_minus& operator++(); + non_const_minus operator++(int); + + long operator-(non_const_minus); +}; + +struct non_integral_minus { + non_integral_minus& operator++(); + non_integral_minus operator++(int); + + void operator-(non_integral_minus); +}; + +struct bad_difference_type_good_minus { + using difference_type = float; + + bad_difference_type_good_minus& operator++(); + void operator++(int); + + int operator-(bad_difference_type_good_minus) const; +}; + +struct missing_default_initializable { + using difference_type = int; + missing_default_initializable() = delete; + + missing_default_initializable& operator++(); + void operator++(int); +}; + +struct missing_movable { + using difference_type = int; + + missing_movable() = default; + missing_movable(missing_movable&&) = delete; + + missing_movable& operator++(); + void operator++(int); +}; + +struct missing_preinc { + using difference_type = int; + + void operator++(int); +}; + +struct missing_postinc { + using difference_type = int; + + missing_postinc& operator++(); +}; + +struct incrementable_with_difference_type { + using difference_type = int; + + incrementable_with_difference_type& operator++(); + incrementable_with_difference_type operator++(int); + + bool operator==(incrementable_with_difference_type const&) const; +}; + +struct incrementable_without_difference_type { + incrementable_without_difference_type& operator++(); + incrementable_without_difference_type operator++(int); + + bool operator==(incrementable_without_difference_type const&) const; + + int operator-(incrementable_without_difference_type) const; +}; + +struct difference_type_and_void_minus { + using difference_type = int; + + difference_type_and_void_minus& operator++(); + difference_type_and_void_minus operator++(int); + + bool operator==(difference_type_and_void_minus const&) const; + + void operator-(difference_type_and_void_minus) const; +}; + +struct noncopyable_with_difference_type { + using difference_type = int; + + noncopyable_with_difference_type() = default; + noncopyable_with_difference_type(noncopyable_with_difference_type&&) = + default; + noncopyable_with_difference_type(noncopyable_with_difference_type const&) = + delete; + + noncopyable_with_difference_type& + operator=(noncopyable_with_difference_type&&) = default; + noncopyable_with_difference_type& + operator=(noncopyable_with_difference_type const&) = delete; + + noncopyable_with_difference_type& operator++(); + noncopyable_with_difference_type operator++(int); + + bool operator==(noncopyable_with_difference_type const&) const; +}; + +struct noncopyable_without_difference_type { + noncopyable_without_difference_type() = default; + noncopyable_without_difference_type(noncopyable_without_difference_type&&) = + default; + noncopyable_without_difference_type( + noncopyable_without_difference_type const&) = delete; + + noncopyable_without_difference_type& + operator=(noncopyable_without_difference_type&&) = default; + noncopyable_without_difference_type& + operator=(noncopyable_without_difference_type const&) = delete; + + noncopyable_without_difference_type& operator++(); + noncopyable_without_difference_type operator++(int); + + int operator-(noncopyable_without_difference_type const&) const; + + bool operator==(noncopyable_without_difference_type const&) const; +}; + +struct noncopyable_with_difference_type_and_minus { + using difference_type = int; + + noncopyable_with_difference_type_and_minus() = default; + noncopyable_with_difference_type_and_minus( + noncopyable_with_difference_type_and_minus&&) = default; + noncopyable_with_difference_type_and_minus( + noncopyable_with_difference_type_and_minus const&) = delete; + + noncopyable_with_difference_type_and_minus& + operator=(noncopyable_with_difference_type_and_minus&&) = default; + noncopyable_with_difference_type_and_minus& + operator=(noncopyable_with_difference_type_and_minus const&) = delete; + + noncopyable_with_difference_type_and_minus& operator++(); + noncopyable_with_difference_type_and_minus operator++(int); + + int operator-(noncopyable_with_difference_type_and_minus const&) const; + + bool operator==(noncopyable_with_difference_type_and_minus const&) const; +}; + +#endif // #define LIBCPP_TEST_STD_ITERATORS_ITERATOR_REQUIREMENTS_ITERATOR_CONCEPTS_INCREMENTABLE_H diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/incrementable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/incrementable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/incrementable.compile.pass.cpp @@ -0,0 +1,202 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// concept indirectly_readable; + +#include + +#include +#include +#include +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../incrementable.h" + +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); + +struct S {}; +static_assert(!std::weakly_incrementable); + +#define CHECK_POINTER_TO_MEMBER_FUNCTIONS(qualifier) \ + static_assert(!std::incrementable); \ + static_assert(!std::incrementable); \ + static_assert(!std::incrementable); \ + static_assert(!std::incrementable); \ + static_assert(!std::incrementable); \ + static_assert(!std::incrementable < int (S::*)() qualifier&& noexcept >); + +#define NO_QUALIFIER +CHECK_POINTER_TO_MEMBER_FUNCTIONS(NO_QUALIFIER); +CHECK_POINTER_TO_MEMBER_FUNCTIONS(const); +CHECK_POINTER_TO_MEMBER_FUNCTIONS(volatile); +CHECK_POINTER_TO_MEMBER_FUNCTIONS(const volatile); + +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); +static_assert(!std::incrementable); + +namespace standard_types { +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(std::incrementable); + +// +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); +static_assert(std::incrementable::reverse_iterator>); +static_assert(std::incrementable::const_reverse_iterator>); + +// +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); +static_assert(std::incrementable::reverse_iterator>); +static_assert(std::incrementable::const_reverse_iterator>); + +// +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +static_assert(!std::incrementable); +static_assert( + !std::incrementable); +#endif + +// +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); + +// +static_assert( + !std::incrementable > >); +static_assert( + !std::incrementable > >); +static_assert(!std::incrementable > >); +static_assert(std::incrementable >); +static_assert(!std::incrementable >); +static_assert( + std::incrementable::iterator> >); +static_assert(!std::incrementable >); +static_assert(!std::incrementable >); + +// +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); +static_assert(std::incrementable::reverse_iterator>); +static_assert(std::incrementable::const_reverse_iterator>); + +// +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); +static_assert(std::incrementable::reverse_iterator>); +static_assert(std::incrementable::const_reverse_iterator>); + +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); +static_assert(std::incrementable::reverse_iterator>); +static_assert( + std::incrementable::const_reverse_iterator>); + +// +static_assert(!std::incrementable >); +static_assert(!std::incrementable >); +static_assert(!std::incrementable >); +static_assert(!std::incrementable >); + +// +static_assert(!std::incrementable >); + +// +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); +static_assert(std::incrementable::reverse_iterator>); +static_assert(std::incrementable::const_reverse_iterator>); + +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); +static_assert(std::incrementable::reverse_iterator>); +static_assert(std::incrementable::const_reverse_iterator>); + +// +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(std::incrementable); + +// +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(std::incrementable); +static_assert(std::incrementable); + +// +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); + +static_assert(std::incrementable::iterator>); +static_assert( + std::incrementable::const_iterator>); + +// +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); + +static_assert(std::incrementable::iterator>); +static_assert( + std::incrementable::const_iterator>); + +// +static_assert(std::incrementable::iterator>); +static_assert(std::incrementable::const_iterator>); +static_assert(std::incrementable::reverse_iterator>); +static_assert(std::incrementable::const_reverse_iterator>); +static_assert(!std::incrementable >); +} // namespace standard_types diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/subsumption.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/subsumption.compile.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// concept incrementable; + +#include + +#include + +// clang-format off +template +requires std::regular +[[nodiscard]] constexpr bool check_subsumption() { + return false; +} + +template +[[nodiscard]] constexpr bool check_subsumption() { + return true; +} +// clang-format on + +static_assert(check_subsumption()); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.winc/subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.winc/subsumption.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.winc/subsumption.compile.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// concept weakly_incrementable; + +#include + +#include + +// clang-format off +template +requires std::movable +[[nodiscard]] constexpr bool check_subsumption() { + return false; +} + +template +[[nodiscard]] constexpr bool check_subsumption() { + return true; +} +// clang-format on + +static_assert(check_subsumption()); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.winc/weakly_incrementable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.winc/weakly_incrementable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.winc/weakly_incrementable.compile.pass.cpp @@ -0,0 +1,222 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// concept std::weakly_incrementable; + +#include + +#include +#include +#include +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../incrementable.h" + +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); + +struct S {}; +static_assert(!std::weakly_incrementable); + +#define CHECK_POINTER_TO_MEMBER_FUNCTIONS(qualifier) \ + static_assert(!std::weakly_incrementable); \ + static_assert(!std::weakly_incrementable); \ + static_assert(!std::weakly_incrementable); \ + static_assert( \ + !std::weakly_incrementable); \ + static_assert(!std::weakly_incrementable); \ + static_assert(!std::weakly_incrementable < int (S::*)() \ + qualifier&& noexcept >); + +#define NO_QUALIFIER +CHECK_POINTER_TO_MEMBER_FUNCTIONS(NO_QUALIFIER); +CHECK_POINTER_TO_MEMBER_FUNCTIONS(const); +CHECK_POINTER_TO_MEMBER_FUNCTIONS(volatile); +CHECK_POINTER_TO_MEMBER_FUNCTIONS(const volatile); + +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert( + std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(!std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert( + std::weakly_incrementable); + +namespace standard_types { +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); + +// +static_assert(std::weakly_incrementable::iterator>); +static_assert(std::weakly_incrementable::const_iterator>); +static_assert(std::weakly_incrementable::reverse_iterator>); +static_assert( + std::weakly_incrementable::const_reverse_iterator>); + +// +static_assert(std::weakly_incrementable::iterator>); +static_assert(std::weakly_incrementable::const_iterator>); +static_assert(std::weakly_incrementable::reverse_iterator>); +static_assert( + std::weakly_incrementable::const_reverse_iterator>); + +// +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +static_assert(std::weakly_incrementable); +static_assert( + std::weakly_incrementable); +#endif + +// +static_assert(std::weakly_incrementable::iterator>); +static_assert( + std::weakly_incrementable::const_iterator>); + +// +static_assert( + !std::weakly_incrementable > >); +static_assert( + !std::weakly_incrementable > >); +static_assert( + !std::weakly_incrementable > >); +static_assert(std::weakly_incrementable >); +static_assert(std::weakly_incrementable >); +static_assert( + std::weakly_incrementable::iterator> >); +static_assert(!std::weakly_incrementable >); +static_assert(!std::weakly_incrementable >); + +// +static_assert(std::weakly_incrementable::iterator>); +static_assert(std::weakly_incrementable::const_iterator>); +static_assert(std::weakly_incrementable::reverse_iterator>); +static_assert( + std::weakly_incrementable::const_reverse_iterator>); + +// +static_assert(std::weakly_incrementable::iterator>); +static_assert(std::weakly_incrementable::const_iterator>); +static_assert(std::weakly_incrementable::reverse_iterator>); +static_assert( + std::weakly_incrementable::const_reverse_iterator>); + +static_assert(std::weakly_incrementable::iterator>); +static_assert( + std::weakly_incrementable::const_iterator>); +static_assert( + std::weakly_incrementable::reverse_iterator>); +static_assert( + std::weakly_incrementable::const_reverse_iterator>); + +// +static_assert(!std::weakly_incrementable >); +static_assert(!std::weakly_incrementable >); +static_assert(!std::weakly_incrementable >); +static_assert(!std::weakly_incrementable >); + +// +static_assert(!std::weakly_incrementable >); + +// +static_assert(std::weakly_incrementable::iterator>); +static_assert(std::weakly_incrementable::const_iterator>); +static_assert(std::weakly_incrementable::reverse_iterator>); +static_assert(std::weakly_incrementable::const_reverse_iterator>); + +static_assert(std::weakly_incrementable::iterator>); +static_assert(std::weakly_incrementable::const_iterator>); +static_assert(std::weakly_incrementable::reverse_iterator>); +static_assert( + std::weakly_incrementable::const_reverse_iterator>); + +// +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); + +// +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert(std::weakly_incrementable); +static_assert( + std::weakly_incrementable); + +// +static_assert( + std::weakly_incrementable::iterator>); +static_assert( + std::weakly_incrementable::const_iterator>); + +static_assert( + std::weakly_incrementable::iterator>); +static_assert(std::weakly_incrementable< + std::unordered_multimap::const_iterator>); + +// +static_assert(std::weakly_incrementable::iterator>); +static_assert( + std::weakly_incrementable::const_iterator>); + +static_assert( + std::weakly_incrementable::iterator>); +static_assert(std::weakly_incrementable< + std::unordered_multiset::const_iterator>); + +// +static_assert(std::weakly_incrementable::iterator>); +static_assert(std::weakly_incrementable::const_iterator>); +static_assert(std::weakly_incrementable::reverse_iterator>); +static_assert( + std::weakly_incrementable::const_reverse_iterator>); +static_assert(!std::weakly_incrementable >); +} // namespace standard_types