[libcxx-commits] [libcxx] 3ec6c99 - [libc++] Implement P1169R4 (static operator())
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Dec 14 17:19:00 PST 2022
Author: Nikolas Klauser
Date: 2022-12-15T02:18:54+01:00
New Revision: 3ec6c997c67d685c533b8c9c2cffde31d834b821
URL: https://github.com/llvm/llvm-project/commit/3ec6c997c67d685c533b8c9c2cffde31d834b821
DIFF: https://github.com/llvm/llvm-project/commit/3ec6c997c67d685c533b8c9c2cffde31d834b821.diff
LOG: [libc++] Implement P1169R4 (static operator())
Reviewed By: ldionne, huixie90, #libc
Spies: EricWF, libcxx-commits, royjacobson
Differential Revision: https://reviews.llvm.org/D135016
Added:
libcxx/include/__type_traits/strip_signature.h
libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.compile.pass.cpp
libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.static.compile.pass.cpp
libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/ctad.static.compile.pass.cpp
Modified:
libcxx/docs/ReleaseNotes.rst
libcxx/docs/Status/Cxx2bIssues.csv
libcxx/docs/Status/Cxx2bPapers.csv
libcxx/include/CMakeLists.txt
libcxx/include/__functional/function.h
libcxx/include/future
libcxx/include/module.modulemap.in
libcxx/test/libcxx/private_headers.verify.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index 2b16ec5475259..3929be5c459ad 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -49,6 +49,7 @@ Implemented Papers
- P2438R2 - ``std::string::substr() &&``
- P0600R1 - ``nodiscard`` in the library
- P0339R6 - ``polymorphic_allocator<>`` as a vocabulary type
+- P1169R4 - ``static operator()``
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv
index 67f46373029e0..756c6869fed24 100644
--- a/libcxx/docs/Status/Cxx2bIssues.csv
+++ b/libcxx/docs/Status/Cxx2bIssues.csv
@@ -1,6 +1,6 @@
"Issue #","Issue Name","Meeting","Status","First released version","Labels"
"`2839 <https://wg21.link/LWG2839>`__","Self-move-assignment of library types, again","November 2020","|Nothing To Do|",""
-"`3117 <https://wg21.link/LWG3117>`__","Missing ``packaged_task`` deduction guides","November 2020","",""
+"`3117 <https://wg21.link/LWG3117>`__","Missing ``packaged_task`` deduction guides","November 2020","|Complete|","16.0"
"`3143 <https://wg21.link/LWG3143>`__","``monotonic_buffer_resource`` growth policy is unclear","November 2020","",""
"`3195 <https://wg21.link/LWG3195>`__","What is the stored pointer value of an empty ``weak_ptr``?","November 2020","|Nothing To Do|",""
"`3211 <https://wg21.link/LWG3211>`__","``std::tuple<>`` should be trivially constructible","November 2020","|Complete|","9.0"
diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv
index e6245261a7d0a..9c98e15c1a7cf 100644
--- a/libcxx/docs/Status/Cxx2bPapers.csv
+++ b/libcxx/docs/Status/Cxx2bPapers.csv
@@ -53,7 +53,7 @@
"","","","","",""
"`P0009R18 <https://wg21.link/P0009R18>`__","LWG","mdspan: A Non-Owning Multidimensional Array Reference","July 2022","",""
"`P0429R9 <https://wg21.link/P0429R9>`__","LWG","A Standard ``flat_map``","July 2022","",""
-"`P1169R4 <https://wg21.link/P1169R4>`__","LWG","``static operator()``","July 2022","",""
+"`P1169R4 <https://wg21.link/P1169R4>`__","LWG","``static operator()``","July 2022","|Complete|","16.0"
"`P1222R4 <https://wg21.link/P1222R4>`__","LWG","A Standard ``flat_set``","July 2022","",""
"`P1223R5 <https://wg21.link/P1223R5>`__","LWG","``ranges::find_last()``, ``ranges::find_last_if()``, and ``ranges::find_last_if_not()``","July 2022","","","|ranges|"
"`P1467R9 <https://wg21.link/P1467R9>`__","LWG","Extended ``floating-point`` types and standard names","July 2022","",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 1c8ce896ada50..62fa8d96d0600 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -672,6 +672,7 @@ set(files
__type_traits/remove_reference.h
__type_traits/remove_volatile.h
__type_traits/result_of.h
+ __type_traits/strip_signature.h
__type_traits/type_identity.h
__type_traits/type_list.h
__type_traits/underlying_type.h
diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h
index 2d9cdc0459d63..436149e88ae37 100644
--- a/libcxx/include/__functional/function.h
+++ b/libcxx/include/__functional/function.h
@@ -23,6 +23,7 @@
#include <__memory/builtin_new_allocator.h>
#include <__memory/compressed_pair.h>
#include <__memory/unique_ptr.h>
+#include <__type_traits/strip_signature.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#include <__utility/piecewise_construct.h>
@@ -1063,45 +1064,6 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)>
template<class _Rp, class ..._Ap>
function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>;
-template<class _Fp>
-struct __strip_signature;
-
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); };
-
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); };
-
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); };
-
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); };
-template<class _Rp, class _Gp, class ..._Ap>
-struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); };
-
template<class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type>
function(_Fp) -> function<_Stripped>;
#endif // _LIBCPP_STD_VER >= 17
diff --git a/libcxx/include/__type_traits/strip_signature.h b/libcxx/include/__type_traits/strip_signature.h
new file mode 100644
index 0000000000000..2bb7393c1ee7f
--- /dev/null
+++ b/libcxx/include/__type_traits/strip_signature.h
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// 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___TYPE_TRAITS_STRIP_SIGNATURE_H
+#define _LIBCPP___TYPE_TRAITS_STRIP_SIGNATURE_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template<class _Fp>
+struct __strip_signature;
+
+# if defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L
+
+template <class _Rp, class... _Args>
+struct __strip_signature<_Rp(*)(_Args...)> {
+ using type = _Rp(_Args...);
+};
+
+template <class _Rp, class... _Args>
+struct __strip_signature<_Rp(*)(_Args...) noexcept> {
+ using type = _Rp(_Args...);
+};
+
+# endif // defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L
+
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); };
+
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); };
+
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); };
+
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); };
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 17
+
+#endif // _LIBCPP___TYPE_TRAITS_STRIP_SIGNATURE_H
diff --git a/libcxx/include/future b/libcxx/include/future
index e317e8d636ef7..a5c1a7bc5cfb1 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -369,6 +369,7 @@ template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>;
#include <__memory/allocator_arg_t.h>
#include <__memory/allocator_destructor.h>
#include <__memory/uses_allocator.h>
+#include <__type_traits/strip_signature.h>
#include <__utility/auto_cast.h>
#include <__utility/forward.h>
#include <__utility/move.h>
@@ -2050,6 +2051,16 @@ public:
void reset();
};
+#if _LIBCPP_STD_VER >= 17
+
+template <class _Rp, class... _Args>
+packaged_task(_Rp(*)(_Args...)) -> packaged_task<_Rp(_Args...)>;
+
+template <class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type>
+packaged_task(_Fp) -> packaged_task<_Stripped>;
+
+#endif
+
template<class ..._ArgTypes>
void
packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args)
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index e6481a823e9b3..4c3a09d1a5f00 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1482,6 +1482,7 @@ module std [system] {
module remove_reference { private header "__type_traits/remove_reference.h" }
module remove_volatile { private header "__type_traits/remove_volatile.h" }
module result_of { private header "__type_traits/result_of.h" }
+ module strip_signature { private header "__type_traits/strip_signature.h" }
module type_identity { private header "__type_traits/type_identity.h" }
module type_list { private header "__type_traits/type_list.h" }
module underlying_type { private header "__type_traits/underlying_type.h" }
diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp
index 55a0c268a579c..23186a9581971 100644
--- a/libcxx/test/libcxx/private_headers.verify.cpp
+++ b/libcxx/test/libcxx/private_headers.verify.cpp
@@ -685,6 +685,7 @@ END-SCRIPT
#include <__type_traits/remove_reference.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/remove_reference.h'}}
#include <__type_traits/remove_volatile.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/remove_volatile.h'}}
#include <__type_traits/result_of.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/result_of.h'}}
+#include <__type_traits/strip_signature.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/strip_signature.h'}}
#include <__type_traits/type_identity.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/type_identity.h'}}
#include <__type_traits/type_list.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/type_list.h'}}
#include <__type_traits/underlying_type.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/underlying_type.h'}}
diff --git a/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.compile.pass.cpp b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.compile.pass.cpp
new file mode 100644
index 0000000000000..0389ed8fccf0a
--- /dev/null
+++ b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.compile.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: no-threads
+// UNSUPPORTED: c++03, c++11, c++14
+
+// checks that CTAD works properly
+
+#include <future>
+#include <type_traits>
+
+int func(char*);
+static_assert(std::is_same_v<decltype(std::packaged_task{func}), std::packaged_task<int(char*)>>);
+
+int funcn(char*) noexcept;
+static_assert(std::is_same_v<decltype(std::packaged_task{funcn}), std::packaged_task<int(char*)>>);
+
+template <bool Noexcept>
+struct Callable {
+ int operator()(char*) noexcept(Noexcept);
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{Callable<true>{}}), std::packaged_task<int(char*)>>);
+static_assert(std::is_same_v<decltype(std::packaged_task{Callable<false>{}}), std::packaged_task<int(char*)>>);
+
+template <bool Noexcept>
+struct CallableC {
+ int operator()(char*) const noexcept(Noexcept);
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableC<true>{}}), std::packaged_task<int(char*)>>);
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableC<false>{}}), std::packaged_task<int(char*)>>);
+
+template <bool Noexcept>
+struct CallableV {
+ int operator()(char*) const noexcept(Noexcept);
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableV<true>{}}), std::packaged_task<int(char*)>>);
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableV<false>{}}), std::packaged_task<int(char*)>>);
+
+template <bool Noexcept>
+struct CallableCV {
+ int operator()(char*) const volatile noexcept(Noexcept);
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableCV<true>{}}), std::packaged_task<int(char*)>>);
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableCV<false>{}}), std::packaged_task<int(char*)>>);
+
+template <bool Noexcept>
+struct CallableL {
+ int operator()(char*) & noexcept(Noexcept);
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableL<true>{}}), std::packaged_task<int(char*)>>);
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableL<false>{}}), std::packaged_task<int(char*)>>);
+
+template <bool Noexcept>
+struct CallableCL {
+ int operator()(char*) const & noexcept(Noexcept);
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableCL<true>{}}), std::packaged_task<int(char*)>>);
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableCL<false>{}}), std::packaged_task<int(char*)>>);
+
+template <bool Noexcept>
+struct CallableVL {
+ int operator()(char*) const noexcept(Noexcept);
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableVL<true>{}}), std::packaged_task<int(char*)>>);
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableVL<false>{}}), std::packaged_task<int(char*)>>);
+
+template <bool Noexcept>
+struct CallableCVL {
+ int operator()(char*) const volatile & noexcept(Noexcept);
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableCVL<true>{}}), std::packaged_task<int(char*)>>);
+static_assert(std::is_same_v<decltype(std::packaged_task{CallableCVL<false>{}}), std::packaged_task<int(char*)>>);
diff --git a/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.static.compile.pass.cpp b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.static.compile.pass.cpp
new file mode 100644
index 0000000000000..f982f22d308b8
--- /dev/null
+++ b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.static.compile.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: no-threads
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// XFAIL: clang-14, clang-15, gcc-12, apple-clang-14
+
+// checks that CTAD for std::packaged_task works properly with static operator() overloads
+
+#include <future>
+#include <type_traits>
+
+struct Except {
+ static int operator()(int*, long*) { return 0; }
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{Except{}}), std::packaged_task<int(int*, long*)>>);
+
+struct Noexcept {
+ static int operator()(int*, long*) noexcept { return 0; }
+};
+static_assert(std::is_same_v<decltype(std::packaged_task{Noexcept{}}), std::packaged_task<int(int*, long*)>>);
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/ctad.static.compile.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/ctad.static.compile.pass.cpp
new file mode 100644
index 0000000000000..df7de4c8aa0cf
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/ctad.static.compile.pass.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// XFAIL: clang-14, clang-15, gcc-12, apple-clang-14
+
+// checks that CTAD for std::function works properly with static operator() overloads
+
+#include <functional>
+#include <type_traits>
+
+struct Except0 {
+ static void operator()() {}
+};
+static_assert(std::is_same_v<decltype(std::function{Except0{}}), std::function<void()>>);
+
+struct Except1 {
+ static int operator()(int&) { return 0; }
+};
+static_assert(std::is_same_v<decltype(std::function{Except1{}}), std::function<int(int&)>>);
+
+struct Except2 {
+ static int operator()(int*, long*) { return 0; }
+};
+static_assert(std::is_same_v<decltype(std::function{Except2{}}), std::function<int(int*, long*)>>);
+
+struct ExceptD {
+ static int operator()(int*, long* = nullptr) { return 0; }
+};
+static_assert(std::is_same_v<decltype(std::function{ExceptD{}}), std::function<int(int*, long*)>>);
+
+struct Noexcept {
+ static int operator()(int*, long*) noexcept { return 0; }
+};
+
+static_assert(std::is_same_v<decltype(std::function{Noexcept{}}), std::function<int(int*, long*)>>);
More information about the libcxx-commits
mailing list