diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -162,6 +162,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 @@ -403,6 +403,10 @@ struct default_sentinel_t; inline constexpr default_sentinel_t default_sentinel{}; +// [unreachable.sentinel], unreachable sentinel +struct unreachable_sentinel_t; +inline constexpr unreachable_sentinel_t unreachable_sentinel{}; + // [iterators.counted], counted iterators template class counted_iterator; @@ -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 @@ -521,6 +521,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/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,40 @@ +//===----------------------------------------------------------------------===// +// +// 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" + +int main(int, char**) { + static_assert(std::is_empty_v); + static_assert(std::semiregular); + + static_assert(std::same_as); + + std::unreachable_sentinel_t s; + for (unsigned i = 0; i < 100; ++i) { + assert(i != s); + assert(i != std::unreachable_sentinel); + } + + int *ptr = nullptr; + assert(s != ptr); + assert(std::unreachable_sentinel != ptr); + + return 0; +}