[libcxx-commits] [libcxx] 910b76a - [libc++] Implement LWG-3655: The INVOKE operation and union types
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Sep 21 02:23:46 PDT 2023
Author: Igor Zhukov
Date: 2023-09-21T05:23:41-04:00
New Revision: 910b76a002713414a7249a7ac8eef52aa8eab748
URL: https://github.com/llvm/llvm-project/commit/910b76a002713414a7249a7ac8eef52aa8eab748
DIFF: https://github.com/llvm/llvm-project/commit/910b76a002713414a7249a7ac8eef52aa8eab748.diff
LOG: [libc++] Implement LWG-3655: The INVOKE operation and union types
https://cplusplus.github.io/LWG/issue3655
Differential Revision: https://reviews.llvm.org/D144645
Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>
Added:
Modified:
libcxx/docs/Status/Cxx23Issues.csv
libcxx/include/__type_traits/invoke.h
libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index 20b0fa7fc9d1fcd..67ef35ec39b2a81 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -280,7 +280,7 @@
"`3622 <https://wg21.link/LWG3622>`__","Misspecified transitivity of equivalence in ยง[unord.req.general]","February 2023","","",""
"`3631 <https://wg21.link/LWG3631>`__","``basic_format_arg(T&&)`` should use ``remove_cvref_t<T>`` throughout","February 2023","|Complete|","17.0",""
"`3645 <https://wg21.link/LWG3645>`__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","February 2023","|Complete|","14.0",""
-"`3655 <https://wg21.link/LWG3655>`__","The ``INVOKE`` operation and union types","February 2023","","",""
+"`3655 <https://wg21.link/LWG3655>`__","The ``INVOKE`` operation and union types","February 2023","|Complete|","18.0",""
"`3723 <https://wg21.link/LWG3723>`__","``priority_queue::push_range`` needs to ``append_range``","February 2023","","","|ranges|"
"`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","","",""
"`3772 <https://wg21.link/LWG3772>`__","``repeat_view``'s ``piecewise`` constructor is missing Postconditions","February 2023","","","|ranges|"
diff --git a/libcxx/include/__type_traits/invoke.h b/libcxx/include/__type_traits/invoke.h
index 5368024955799bf..a6463bfa5904228 100644
--- a/libcxx/include/__type_traits/invoke.h
+++ b/libcxx/include/__type_traits/invoke.h
@@ -240,7 +240,8 @@ template <class _Fp,
class _DecayA0 = __decay_t<_A0>,
class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
using __enable_if_bullet1 =
- __enable_if_t<is_member_function_pointer<_DecayFp>::value && is_base_of<_ClassT, _DecayA0>::value>;
+ __enable_if_t<is_member_function_pointer<_DecayFp>::value &&
+ (is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value)>;
template <class _Fp, class _A0, class _DecayFp = __decay_t<_Fp>, class _DecayA0 = __decay_t<_A0> >
using __enable_if_bullet2 =
@@ -252,7 +253,8 @@ template <class _Fp,
class _DecayA0 = __decay_t<_A0>,
class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
using __enable_if_bullet3 =
- __enable_if_t<is_member_function_pointer<_DecayFp>::value && !is_base_of<_ClassT, _DecayA0>::value &&
+ __enable_if_t<is_member_function_pointer<_DecayFp>::value &&
+ !(is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value) &&
!__is_reference_wrapper<_DecayA0>::value>;
template <class _Fp,
@@ -261,7 +263,8 @@ template <class _Fp,
class _DecayA0 = __decay_t<_A0>,
class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
using __enable_if_bullet4 =
- __enable_if_t<is_member_object_pointer<_DecayFp>::value && is_base_of<_ClassT, _DecayA0>::value>;
+ __enable_if_t<is_member_object_pointer<_DecayFp>::value &&
+ (is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value)>;
template <class _Fp, class _A0, class _DecayFp = __decay_t<_Fp>, class _DecayA0 = __decay_t<_A0> >
using __enable_if_bullet5 =
@@ -273,7 +276,8 @@ template <class _Fp,
class _DecayA0 = __decay_t<_A0>,
class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
using __enable_if_bullet6 =
- __enable_if_t<is_member_object_pointer<_DecayFp>::value && !is_base_of<_ClassT, _DecayA0>::value &&
+ __enable_if_t<is_member_object_pointer<_DecayFp>::value &&
+ !(is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value) &&
!__is_reference_wrapper<_DecayA0>::value>;
// __invoke forward declarations
diff --git a/libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp b/libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp
index 82849a815e7e330..54499c08ad144bc 100644
--- a/libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp
@@ -346,6 +346,75 @@ void noexcept_test() {
}
}
+// LWG3655: The INVOKE operation and union types
+void union_tests() {
+ union Union {
+ int x;
+ int f() { return 42; }
+ int g() const { return 52; }
+ };
+
+ // With a data member
+ {
+ auto get = []() -> Union { return Union{.x = 3}; };
+ int result = std::invoke(&Union::x, get());
+ assert(result == 3);
+ }
+ {
+ auto get = []() -> Union const { return Union{.x = 3}; };
+ int result = std::invoke(&Union::x, get());
+ assert(result == 3);
+ }
+ {
+ Union u{3};
+ int& result = std::invoke(&Union::x, u);
+ assert(&result == &u.x);
+ }
+ {
+ Union const u{3};
+ int const& result = std::invoke(&Union::x, u);
+ assert(&result == &u.x);
+ }
+
+ // With a pointer to a member function
+ {
+ auto get = []() -> Union { return Union{.x = 3}; };
+ int result = std::invoke(&Union::f, get());
+ assert(result == 42);
+ }
+ {
+ Union u{3};
+ int result = std::invoke(&Union::f, u);
+ assert(result == 42);
+ }
+ {
+ // constness mismatch
+ static_assert(!std::is_invocable_v<int (Union::*)(), Union const>);
+ static_assert(!std::is_invocable_v<int (Union::*)(), Union const&>);
+ }
+
+ {
+ auto get = []() -> Union { return Union{.x = 3}; };
+ int result = std::invoke(&Union::g, get());
+ assert(result == 52);
+ }
+ {
+ auto get = []() -> Union const { return Union{.x = 3}; };
+ int result = std::invoke(&Union::g, get());
+ assert(result == 52);
+ }
+ {
+ Union u{3};
+ int result = std::invoke(&Union::g, u);
+ assert(result == 52);
+ }
+ {
+ Union const u{3};
+ int result = std::invoke(&Union::g, u);
+ assert(result == 52);
+ }
+}
+
int main(int, char**) {
bullet_one_two_tests();
bullet_three_four_tests();
More information about the libcxx-commits
mailing list