diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -186,6 +186,7 @@ __iterator/reverse_access.h __iterator/reverse_iterator.h __iterator/size.h + __iterator/unreachable_sentinel.h __iterator/wrap_iter.h __libcpp_version __locale diff --git a/libcxx/include/__iterator/unreachable_sentinel.h b/libcxx/include/__iterator/unreachable_sentinel.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__iterator/unreachable_sentinel.h @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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___ITERATOR_UNREACHABLE_SENTINEL_H +#define _LIBCPP___ITERATOR_UNREACHABLE_SENTINEL_H + +#include <__config> +#include <__iterator/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_RANGES) + +struct unreachable_sentinel_t { + template + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(unreachable_sentinel_t, const _Iter&) noexcept { + return false; + } +}; + +inline constexpr unreachable_sentinel_t unreachable_sentinel{}; + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_UNREACHABLE_SENTINEL_H diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -410,6 +410,10 @@ requires see below struct iterator_traits>; +// [unreachable.sentinel], unreachable sentinel +struct unreachable_sentinel_t; +inline constexpr unreachable_sentinel_t unreachable_sentinel{}; + template , class Distance = ptrdiff_t> class istream_iterator : public iterator // until C++17 @@ -606,6 +610,7 @@ #include <__iterator/reverse_access.h> #include <__iterator/reverse_iterator.h> #include <__iterator/size.h> +#include <__iterator/unreachable_sentinel.h> #include <__iterator/wrap_iter.h> #include <__memory/addressof.h> #include <__memory/pointer_traits.h> diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -548,6 +548,7 @@ module reverse_access { private header "__iterator/reverse_access.h" } module reverse_iterator { private header "__iterator/reverse_iterator.h" } module size { private header "__iterator/size.h" } + module unreachable_sentinel { private header "__iterator/unreachable_sentinel.h" } module wrap_iter { private header "__iterator/wrap_iter.h" } } } diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/unreachable_sentinel.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/unreachable_sentinel.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/unreachable_sentinel.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/unreachable_sentinel.h'}} +#include <__iterator/unreachable_sentinel.h> diff --git a/libcxx/test/std/iterators/predef.iterators/unreachable.sentinel/unreachable_sentinel.pass.cpp b/libcxx/test/std/iterators/predef.iterators/unreachable.sentinel/unreachable_sentinel.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/unreachable.sentinel/unreachable_sentinel.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// struct unreachable_sentinel_t; +// inline constexpr unreachable_sentinel_t unreachable_sentinel; + +#include + +#include +#include +#include + +#include "test_macros.h" + +template +concept weakly_equality_comparable_with = requires(const T& t, const U& u) { + { t == u } -> std::same_as; + { t != u } -> std::same_as; + { u == t } -> std::same_as; + { u != t } -> std::same_as; +}; + +constexpr bool test() { + static_assert(std::is_empty_v); + static_assert(std::semiregular); + + static_assert(std::same_as); + + auto sentinel = std::unreachable_sentinel; + int i = 42; + assert(i != sentinel); + assert(sentinel != i); + assert(!(i == sentinel)); + assert(!(sentinel == i)); + + assert(&i != sentinel); + assert(sentinel != &i); + assert(!(&i == sentinel)); + assert(!(sentinel == &i)); + + int *p = nullptr; + assert(p != sentinel); + assert(sentinel != p); + assert(!(p == sentinel)); + assert(!(sentinel == p)); + + static_assert( weakly_equality_comparable_with); + static_assert( weakly_equality_comparable_with); + static_assert(!weakly_equality_comparable_with); + ASSERT_NOEXCEPT(sentinel == p); + ASSERT_NOEXCEPT(sentinel != p); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +}