diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index d30021b7eb234..f72e13cf6d9af 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -46,6 +46,7 @@ Implemented Papers - P2872R3 - Remove ``wstring_convert`` From C++26 - P3142R0 - Printing Blank Lines with ``println`` (as DR against C++23) - P2944R3 - Comparisons for ``reference_wrapper`` (comparison operators for ``reference_wrapper`` only) +- P2968R2 - Make ``std::ignore`` a first-class object - P2302R4 - ``std::ranges::contains`` - P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with`` - P3029R1 - Better ``mdspan``'s CTAD @@ -74,6 +75,9 @@ Improvements and New Features - The formatting library is updated to Unicode 15.1.0. +- ``std::ignore``\s ``const __ignore_t& operator=(_Tp&&) const`` was changed to + ``const __ignore_type& operator=(const _Tp&) const noexcept`` for all language versions. + Deprecations and Removals ------------------------- diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index 48d45e24a05b2..aea413dd33588 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -71,7 +71,7 @@ "`P2985R0 `__","LWG","A type trait for detecting virtual base classes","St. Louis June 2024","","","" "`P0843R14 `__","LWG","``inplace_vector``","St. Louis June 2024","","","" "`P3235R3 `__","LWG","``std::print`` more types faster with less memory","St. Louis June 2024","","","|format| |DR|" -"`P2968R2 `__","LWG","Make ``std::ignore`` a first-class object","St. Louis June 2024","","","" +"`P2968R2 `__","LWG","Make ``std::ignore`` a first-class object","St. Louis June 2024","|Complete|","19.0","" "`P2075R6 `__","LWG","Philox as an extension of the C++ RNG engines","St. Louis June 2024","","","" "`P2422R1 `__","LWG","Remove ``nodiscard`` annotations from the standard library specification","St. Louis June 2024","|Complete| [#note-P2422R1]_","19.0","" "`P2300R10 `__","LWG","``std::execution``","St. Louis June 2024","","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 8d0ffd6ed725b..07dd25604a9c7 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -710,6 +710,7 @@ set(files __thread/timed_backoff_policy.h __tree __tuple/find_index.h + __tuple/ignore.h __tuple/make_tuple_types.h __tuple/sfinae_helpers.h __tuple/tuple_element.h diff --git a/libcxx/include/__tuple/ignore.h b/libcxx/include/__tuple/ignore.h new file mode 100644 index 0000000000000..43cce5387411b --- /dev/null +++ b/libcxx/include/__tuple/ignore.h @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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___TUPLE_IGNORE_H +#define _LIBCPP___TUPLE_IGNORE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_CXX03_LANG + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __ignore_type { + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const __ignore_type& operator=(const _Tp&) const noexcept { + return *this; + } +}; + +# if _LIBCPP_STD_VER >= 17 +inline constexpr __ignore_type ignore; +# else +constexpr __ignore_type ignore; +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_CXX03_LANG + +#endif // _LIBCPP___TUPLE_IGNORE_H diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 9ffccf66ff094..4ad506781c489 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -1840,6 +1840,7 @@ module std_private_thread_thread [system] { module std_private_thread_timed_backoff_policy [system] { header "__thread/timed_backoff_policy.h" } module std_private_tuple_find_index [system] { header "__tuple/find_index.h" } +module std_private_tuple_ignore [system] { header "__tuple/ignore.h" } module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" } module std_private_tuple_tuple_like_no_subrange [system] { header "__tuple/tuple_like_no_subrange.h" diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 26652ffe81e9f..081b90c7bbec5 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -132,7 +132,12 @@ tuple(allocator_arg_t, Alloc, pair) -> tuple; // since C++ template tuple(allocator_arg_t, Alloc, tuple) -> tuple; // since C++17 -inline constexpr unspecified ignore; +struct ignore-type { // exposition only // Since C++26 + constexpr const ignore-type& + operator=(const auto &) const noexcept + { return *this; } +}; +inline constexpr ignore-type ignore; template tuple make_tuple(T&&...); // constexpr in C++14 template tuple forward_as_tuple(T&&...) noexcept; // constexpr in C++14 @@ -215,6 +220,7 @@ template #include <__memory/allocator_arg_t.h> #include <__memory/uses_allocator.h> #include <__tuple/find_index.h> +#include <__tuple/ignore.h> #include <__tuple/make_tuple_types.h> #include <__tuple/sfinae_helpers.h> #include <__tuple/tuple_element.h> @@ -1112,22 +1118,6 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&...> tie(_T return tuple<_Tp&...>(__t...); } -template -struct __ignore_t { - template - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const __ignore_t& operator=(_Tp&&) const { - return *this; - } -}; - -# if _LIBCPP_STD_VER >= 17 -inline constexpr __ignore_t ignore = __ignore_t(); -# else -namespace { -constexpr __ignore_t ignore = __ignore_t(); -} // namespace -# endif - template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple::type...> make_tuple(_Tp&&... __t) { diff --git a/libcxx/include/utility b/libcxx/include/utility index 90713da621c5d..f2f0052df2755 100644 --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -274,6 +274,10 @@ template #include #include +// [tuple.creation] + +#include <__tuple/ignore.h> + // [tuple.helper] #include <__tuple/tuple_element.h> #include <__tuple/tuple_size.h> diff --git a/libcxx/test/std/utilities/tuple/tuple.general/ignore.include.compile.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.general/ignore.include.compile.pass.cpp new file mode 100644 index 0000000000000..0fdf0d0af52b9 --- /dev/null +++ b/libcxx/test/std/utilities/tuple/tuple.general/ignore.include.compile.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + +// inline constexpr ignore-type ignore; + +// std::ignore should be provided by the headers and . +// This test validates its presence in . + +#include + +[[maybe_unused]] auto& ignore_v = std::ignore; diff --git a/libcxx/test/std/utilities/tuple/tuple.general/ignore.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.general/ignore.pass.cpp index 769c55e10fc43..525ffde5cf177 100644 --- a/libcxx/test/std/utilities/tuple/tuple.general/ignore.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.general/ignore.pass.cpp @@ -6,51 +6,64 @@ // //===----------------------------------------------------------------------===// -// +// UNSUPPORTED: c++03 -// constexpr unspecified ignore; +// -// UNSUPPORTED: c++03 +// inline constexpr ignore-type ignore; #include +#include #include #include #include "test_macros.h" -constexpr bool test_ignore_constexpr() -{ -#if TEST_STD_VER > 11 - { // Test that std::ignore provides constexpr converting assignment. - auto& res = (std::ignore = 42); - assert(&res == &std::ignore); - } - { // Test that std::ignore provides constexpr copy/move constructors - auto copy = std::ignore; - auto moved = std::move(copy); - ((void)moved); - } - { // Test that std::ignore provides constexpr copy/move assignment - auto copy = std::ignore; - copy = std::ignore; - auto moved = std::ignore; - moved = std::move(copy); - } +static_assert(std::is_trivial::value, ""); + +#if TEST_STD_VER >= 17 +[[nodiscard]] constexpr int test_nodiscard() { return 8294; } #endif - return true; + +TEST_CONSTEXPR_CXX14 bool test() { + { [[maybe_unused]] auto& ignore_v = std::ignore; } + + { // Test that std::ignore provides converting assignment. + auto& res = (std::ignore = 42); + static_assert(noexcept(res = (std::ignore = 42)), "Must be noexcept"); + assert(&res == &std::ignore); + } + { // Test bit-field binding. + struct S { + unsigned int bf : 3; + }; + S s{0b010}; + auto& res = (std::ignore = s.bf); + assert(&res == &std::ignore); + } + { // Test that std::ignore provides copy/move constructors + auto copy = std::ignore; + [[maybe_unused]] auto moved = std::move(copy); + } + { // Test that std::ignore provides copy/move assignment + auto copy = std::ignore; + copy = std::ignore; + auto moved = std::ignore; + moved = std::move(copy); + } + +#if TEST_STD_VER >= 17 + { std::ignore = test_nodiscard(); } +#endif + + return true; } int main(int, char**) { - { - constexpr auto& ignore_v = std::ignore; - ((void)ignore_v); - } - { - static_assert(test_ignore_constexpr(), ""); - } - { - LIBCPP_STATIC_ASSERT(std::is_trivial::value, ""); - } + test(); +#if TEST_STD_VER >= 14 + static_assert(test(), ""); +#endif return 0; } diff --git a/libcxx/test/std/utilities/utility/ignore/ignore.include.compile.pass.cpp b/libcxx/test/std/utilities/utility/ignore/ignore.include.compile.pass.cpp new file mode 100644 index 0000000000000..3aa74397acf20 --- /dev/null +++ b/libcxx/test/std/utilities/utility/ignore/ignore.include.compile.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + +// inline constexpr ignore-type ignore; + +// std::ignore should be provided by the headers and . +// This test validates its presence in . + +#include + +[[maybe_unused]] auto& ignore_v = std::ignore;