Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[libc++] Simplify the implementation of std::get for pairs #114984

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

philnik777
Copy link
Contributor

@philnik777 philnik777 commented Nov 5, 2024

This makes it clearer what the functions actually do. As a nice side-effect it also avoids a function call. If the C++03 header split is successful we could drop __get_pair entirely.

}

template <class _T1, class _T2>
inline _LIBCPP_HIDE_FROM_ABI constexpr _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
return __get_pair<0>::get(std::move(__p));
return std::forward<_T1&&>(std::move(__p).first);
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be better to just use static_cast (ditto below)?

Suggested change
return std::forward<_T1&&>(std::move(__p).first);
return static_cast<_T1&&>(__p.first);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why do you think that a static_cast would be better?

Copy link
Contributor

Choose a reason for hiding this comment

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

IMO given it's necessary spell out the resulted reference type anyway, it would be clearer to just use a cast.

@philnik777 philnik777 force-pushed the simplify_pair branch 3 times, most recently from 5d09660 to 4333081 Compare November 10, 2024 12:30
@philnik777 philnik777 marked this pull request as ready for review November 11, 2024 23:04
@philnik777 philnik777 requested a review from a team as a code owner November 11, 2024 23:04
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Nov 11, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 11, 2024

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

This makes it clearer what the functions actually do. As a nice side-effect it also avoids a function call. If the C++03 header split is successful we could drop __get_pair entirely.


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

2 Files Affected:

  • (modified) libcxx/include/__utility/pair.h (+8-8)
  • (added) libcxx/test/std/utilities/utility/pairs/pair.astuple/get_ref.pass.cpp (+68)
diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h
index f9d0f4e4723113..17631277691108 100644
--- a/libcxx/include/__utility/pair.h
+++ b/libcxx/include/__utility/pair.h
@@ -633,42 +633,42 @@ get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
 #if _LIBCPP_STD_VER >= 14
 template <class _T1, class _T2>
 inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(pair<_T1, _T2>& __p) _NOEXCEPT {
-  return __get_pair<0>::get(__p);
+  return __p.first;
 }
 
 template <class _T1, class _T2>
 inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const& get(pair<_T1, _T2> const& __p) _NOEXCEPT {
-  return __get_pair<0>::get(__p);
+  return __p.first;
 }
 
 template <class _T1, class _T2>
 inline _LIBCPP_HIDE_FROM_ABI constexpr _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
-  return __get_pair<0>::get(std::move(__p));
+  return std::forward<_T1&&>(__p.first);
 }
 
 template <class _T1, class _T2>
 inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(pair<_T1, _T2> const&& __p) _NOEXCEPT {
-  return __get_pair<0>::get(std::move(__p));
+  return std::forward<_T1 const&&>(__p.first);
 }
 
 template <class _T1, class _T2>
 inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(pair<_T2, _T1>& __p) _NOEXCEPT {
-  return __get_pair<1>::get(__p);
+  return __p.second;
 }
 
 template <class _T1, class _T2>
 inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const& get(pair<_T2, _T1> const& __p) _NOEXCEPT {
-  return __get_pair<1>::get(__p);
+  return __p.second;
 }
 
 template <class _T1, class _T2>
 inline _LIBCPP_HIDE_FROM_ABI constexpr _T1&& get(pair<_T2, _T1>&& __p) _NOEXCEPT {
-  return __get_pair<1>::get(std::move(__p));
+  return std::forward<_T1&&>(__p.second);
 }
 
 template <class _T1, class _T2>
 inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(pair<_T2, _T1> const&& __p) _NOEXCEPT {
-  return __get_pair<1>::get(std::move(__p));
+  return std::forward<_T1 const&&>(__p.second);
 }
 
 #endif // _LIBCPP_STD_VER >= 14
diff --git a/libcxx/test/std/utilities/utility/pairs/pair.astuple/get_ref.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pair.astuple/get_ref.pass.cpp
new file mode 100644
index 00000000000000..4343361930959c
--- /dev/null
+++ b/libcxx/test/std/utilities/utility/pairs/pair.astuple/get_ref.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <utility>
+
+// template <class T1, class T2> struct pair
+
+// template<size_t I, class T1, class T2>
+//     typename tuple_element<I, std::pair<T1, T2> >::type&&
+//     get(pair<T1, T2>&&);
+
+#include <cassert>
+#include <utility>
+
+#include "test_macros.h"
+
+TEST_CONSTEXPR_CXX14 bool test() {
+  int i = 1;
+  int j = 2;
+
+  {
+    std::pair<int&, int&&> p(i, std::move(j));
+    assert(&std::get<int&>(p) == &i);
+    assert(&std::get<int&&>(p) == &j);
+
+    assert(&std::get<int&>(std::move(p)) == &i);
+    assert(std::get<int&&>(std::move(p)) == 2);
+
+    const std::pair<int&, int&&> cp(i, std::move(j));
+    assert(&std::get<int&>(cp) == &i);
+    assert(&std::get<int&&>(cp) == &j);
+
+    assert(&std::get<int&>(std::move(cp)) == &i);
+    assert(std::get<int&&>(std::move(cp)) == 2);
+  }
+
+  {
+    std::pair<int&&, int&> p(std::move(i), j);
+    assert(&std::get<int&>(p) == &j);
+    assert(&std::get<int&&>(p) == &i);
+
+    assert(&std::get<int&>(std::move(p)) == &j);
+    assert(std::get<int&&>(std::move(p)) == 1);
+
+    const std::pair<int&&, int&> cp(std::move(i), j);
+    assert(&std::get<int&>(cp) == &j);
+    assert(&std::get<int&&>(cp) == &i);
+
+    assert(&std::get<int&>(std::move(cp)) == &j);
+    assert(std::get<int&&>(std::move(cp)) == 1);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+#if TEST_STD_VER >= 14
+  static_assert(test(), "");
+#endif
+}

Copy link

github-actions bot commented Mar 27, 2025

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

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the simplification.

@philnik777 philnik777 force-pushed the simplify_pair branch 2 times, most recently from 54b6c87 to b2cd819 Compare May 7, 2025 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants