Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libcxx] Put std::monostate in <utility> #128373

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

AmrDeveloper
Copy link
Member

Fixes: #127874

@AmrDeveloper AmrDeveloper requested a review from a team as a code owner February 22, 2025 22:14
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Feb 22, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 22, 2025

@llvm/pr-subscribers-libcxx

Author: Amr Hesham (AmrDeveloper)

Changes

Fixes: #127874


Full diff: https://github.com/llvm/llvm-project/pull/128373.diff

6 Files Affected:

  • (modified) libcxx/docs/ReleaseNotes/21.rst (+1)
  • (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1-1)
  • (added) libcxx/include/__cxx03/__utility/monostate.h (+65)
  • (added) libcxx/include/__utility/monostate.h (+66)
  • (added) libcxx/test/std/utilities/utility/utility.monostate.relpos/relops.pass.cpp (+47)
  • (added) libcxx/test/std/utilities/utility/utility.monostate/monostate.pass.cpp (+31)
diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst
index 30c6cc5eaf0c2..d1935c8af02e0 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -40,6 +40,7 @@ Implemented Papers
 
 - N4258: Cleaning-up noexcept in the Library (`Github <https://github.com/llvm/llvm-project/issues/99937>`__)
 - P1361R2: Integration of chrono with text formatting (`Github <https://github.com/llvm/llvm-project/issues/100014>`__)
+- P0472R3: Put std::monostate in <utility> (`Github <https://github.com/llvm/llvm-project/issues/127874`__)
 
 Improvements and New Features
 -----------------------------
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 1436db6cf2b45..a47cc193382da 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -102,7 +102,7 @@
 "`P3475R2 <https://wg21.link/P3475R2>`__","Defang and deprecate ``memory_order::consume``","2025-02 (Hagenberg)","","",""
 "`P2786R13 <https://wg21.link/P2786R13>`__","Trivial Relocatability For C++26","2025-02 (Hagenberg)","","",""
 "`P3137R3 <https://wg21.link/P3137R3>`__","``views::to_input``","2025-02 (Hagenberg)","","",""
-"`P0472R3 <https://wg21.link/P0472R3>`__","Put ``std::monostate`` in ``<utility>``","2025-02 (Hagenberg)","","",""
+"`P0472R3 <https://wg21.link/P0472R3>`__","Put ``std::monostate`` in ``<utility>``","2025-02 (Hagenberg)","|Complete|","21",""
 "`P3349R1 <https://wg21.link/P3349R1>`__","Converting contiguous iterators to pointers","2025-02 (Hagenberg)","","",""
 "`P3372R3 <https://wg21.link/P3372R3>`__","constexpr containers and adaptors","2025-02 (Hagenberg)","","",""
 "`P3378R2 <https://wg21.link/P3378R2>`__","constexpr exception types","2025-02 (Hagenberg)","","",""
diff --git a/libcxx/include/__cxx03/__utility/monostate.h b/libcxx/include/__cxx03/__utility/monostate.h
new file mode 100644
index 0000000000000..486a18bfa54ca
--- /dev/null
+++ b/libcxx/include/__cxx03/__utility/monostate.h
@@ -0,0 +1,65 @@
+
+// -*- 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___CXX03___UTILITY_MONOSTATE_H
+#define _LIBCPP___CXX03___UTILITY_MONOSTATE_H
+
+#include <__cxx03/__compare/ordering.h>
+#include <__cxx03/__config>
+#include <__cxx03/__functional/hash.h>
+#include <__cxx03/cstddef>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 17
+
+struct _LIBCPP_TEMPLATE_VIS monostate {};
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(monostate, monostate) noexcept { return true; }
+
+#  if _LIBCPP_STD_VER >= 20
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr strong_ordering operator<=>(monostate, monostate) noexcept {
+  return strong_ordering::equal;
+}
+
+#  else // _LIBCPP_STD_VER >= 20
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator!=(monostate, monostate) noexcept { return false; }
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator<(monostate, monostate) noexcept { return false; }
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator>(monostate, monostate) noexcept { return false; }
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator<=(monostate, monostate) noexcept { return true; }
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator>=(monostate, monostate) noexcept { return true; }
+
+#  endif // _LIBCPP_STD_VER >= 20
+
+template <>
+struct _LIBCPP_TEMPLATE_VIS hash<monostate> {
+  using argument_type = monostate;
+  using result_type   = size_t;
+
+  inline _LIBCPP_HIDE_FROM_ABI result_type operator()(const argument_type&) const _NOEXCEPT {
+    return 66740831; // return a fundamentally attractive random value.
+  }
+};
+
+#endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___CXX03___UTILITY_MONOSTATE_H
diff --git a/libcxx/include/__utility/monostate.h b/libcxx/include/__utility/monostate.h
new file mode 100644
index 0000000000000..3a2a659228e1c
--- /dev/null
+++ b/libcxx/include/__utility/monostate.h
@@ -0,0 +1,66 @@
+// -*- 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___UTILITY_MONOSTATE_H
+#define _LIBCPP___UTILITY_MONOSTATE_H
+
+#include <__compare/ordering.h>
+#include <__configUTILITY>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 17
+
+struct _LIBCPP_TEMPLATE_VIS monostate {};
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(monostate, monostate) noexcept { return true; }
+
+#  if _LIBCPP_STD_VER >= 20
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr strong_ordering operator<=>(monostate, monostate) noexcept {
+  return strong_ordering::equal;
+}
+
+#  else // _LIBCPP_STD_VER >= 20
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator!=(monostate, monostate) noexcept { return false; }
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator<(monostate, monostate) noexcept { return false; }
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator>(monostate, monostate) noexcept { return false; }
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator<=(monostate, monostate) noexcept { return true; }
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator>=(monostate, monostate) noexcept { return true; }
+
+#  endif // _LIBCPP_STD_VER >= 20
+
+template <>
+struct _LIBCPP_TEMPLATE_VIS hash<monostate> {
+#  if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
+  using argument_type _LIBCPP_DEPRECATED_IN_CXX17 = monostate;
+  using result_type _LIBCPP_DEPRECATED_IN_CXX17   = size_t;
+#  endif
+
+  inline _LIBCPP_HIDE_FROM_ABI size_t operator()(const monostate&) const noexcept {
+    return 66740831; // return a fundamentally attractive random value.
+  }
+};
+
+#endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___UTILITY_MONOSTATE_H
diff --git a/libcxx/test/std/utilities/utility/utility.monostate.relpos/relops.pass.cpp b/libcxx/test/std/utilities/utility/utility.monostate.relpos/relops.pass.cpp
new file mode 100644
index 0000000000000..f29d89acdc739
--- /dev/null
+++ b/libcxx/test/std/utilities/utility/utility.monostate.relpos/relops.pass.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20, c++23
+
+// <utility>
+
+// constexpr bool operator<(monostate, monostate) noexcept { return false; }
+// constexpr bool operator>(monostate, monostate) noexcept { return false; }
+// constexpr bool operator<=(monostate, monostate) noexcept { return true; }
+// constexpr bool operator>=(monostate, monostate) noexcept { return true; }
+// constexpr bool operator==(monostate, monostate) noexcept { return true; }
+// constexpr bool operator!=(monostate, monostate) noexcept { return false; }
+// constexpr strong_ordering operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; } // since C++20
+
+#include <cassert>
+#include <utility>
+
+#include "test_comparisons.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+  using M = std::monostate;
+  constexpr M m1{};
+  constexpr M m2{};
+  assert(testComparisons(m1, m2, /*isEqual*/ true, /*isLess*/ false));
+  AssertComparisonsAreNoexcept<M>();
+
+#if TEST_STD_VER > 17
+  assert(testOrder(m1, m2, std::strong_ordering::equal));
+  AssertOrderAreNoexcept<M>();
+#endif // TEST_STD_VER > 17
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/utility/utility.monostate/monostate.pass.cpp b/libcxx/test/std/utilities/utility/utility.monostate/monostate.pass.cpp
new file mode 100644
index 0000000000000..c78ce5a5c2f18
--- /dev/null
+++ b/libcxx/test/std/utilities/utility/utility.monostate/monostate.pass.cpp
@@ -0,0 +1,31 @@
+
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20, c++23
+
+// <utility>
+
+// struct monostate {};
+
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  using M = std::monostate;
+  static_assert(std::is_trivially_default_constructible<M>::value, "");
+  static_assert(std::is_trivially_copy_constructible<M>::value, "");
+  static_assert(std::is_trivially_copy_assignable<M>::value, "");
+  static_assert(std::is_trivially_destructible<M>::value, "");
+  constexpr M m{};
+  ((void)m);
+
+  return 0;
+}

@AmrDeveloper AmrDeveloper added c++26 wg21 paper Issues representing the implementation of a WG21 paper labels Feb 22, 2025
Copy link

github-actions bot commented Feb 23, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@AmrDeveloper
Copy link
Member Author

@frederick-vs-ja

4 unreleased tests fail from 77, I will rebase and rerun it after addressing your new code review comments, if there is a new comments :D

Copy link
Contributor

@frederick-vs-ja frederick-vs-ja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test failure seem due to unrelated reasons. Let's wait for the fix.

I guess some maintainers want to implement this in C++17 (as a conforming extension).

@@ -279,6 +279,10 @@ template <class T>
# include <__utility/unreachable.h>
# endif

# if _LIBCPP_STD_VER >= 26
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess some maintainers want this to be in the # if _LIBCPP_STD_VER >= 17 region, although I have no strong preference.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okey, i will make it from C++17

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong preference. Making it available from 17 as an extension seems fine. It's a really small header with few dependencies.

//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use // REQUIRES: std-at-least-c++26 in both test files, but see the comment above.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@frederick-vs-ja Is that something new? When was this introduced?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This was introduced in #89499.

@AmrDeveloper AmrDeveloper force-pushed the put_monostate_in_utility branch from b373a40 to b0a68ea Compare February 24, 2025 17:50
@AmrDeveloper AmrDeveloper force-pushed the put_monostate_in_utility branch from 282cfac to 495c7e7 Compare February 27, 2025 20:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++26 libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. wg21 paper Issues representing the implementation of a WG21 paper
Projects
None yet
Development

Successfully merging this pull request may close these issues.

P0472R3: Put std::monostate in <utility>
5 participants