diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -44,6 +44,7 @@ - P0591R4 - Utility functions to implement uses-allocator construction - P2291R3 - Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ```` Header +- P1169R4 - ``static operator()`` Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv --- 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 `__","Self-move-assignment of library types, again","November 2020","|Nothing To Do|","" -"`3117 `__","Missing ``packaged_task`` deduction guides","November 2020","","" +"`3117 `__","Missing ``packaged_task`` deduction guides","November 2020","|Complete|","16.0" "`3143 `__","``monotonic_buffer_resource`` growth policy is unclear","November 2020","","" "`3195 `__","What is the stored pointer value of an empty ``weak_ptr``?","November 2020","|Nothing To Do|","" "`3211 `__","``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 --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -53,7 +53,7 @@ "","","","","","" "`P0009R18 `__","LWG","mdspan: A Non-Owning Multidimensional Array Reference","July 2022","","" "`P0429R9 `__","LWG","A Standard ``flat_map``","July 2022","","" -"`P1169R4 `__","LWG","``static operator()``","July 2022","","" +"`P1169R4 `__","LWG","``static operator()``","July 2022","|Complete|","16.0" "`P1222R4 `__","LWG","A Standard ``flat_set``","July 2022","","" "`P1223R5 `__","LWG","``ranges::find_last()``, ``ranges::find_last_if()``, and ``ranges::find_last_if_not()``","July 2022","","" "`P1467R9 `__","LWG","Extended ``floating-point`` types and standard names","July 2022","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -663,6 +663,7 @@ __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 --- a/libcxx/include/__functional/function.h +++ b/libcxx/include/__functional/function.h @@ -23,6 +23,7 @@ #include <__memory/compressed_pair.h> #include <__memory/shared_ptr.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 @@ template function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>; -template -struct __strip_signature; - -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); }; - -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); }; - -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); }; - -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); }; -template -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); }; - template::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 --- /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 +struct __strip_signature; + +# if defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L + +template +struct __strip_signature<_Rp(*)(_Args...)> { + using type = _Rp(_Args...); +}; + +template +struct __strip_signature<_Rp(*)(_Args...) noexcept> { + using type = _Rp(_Args...); +}; + +# endif // defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L + +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); }; + +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); }; + +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); }; + +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); }; +template +struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); }; +template +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 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -368,6 +368,7 @@ #include <__config> #include <__memory/allocator_arg_t.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> @@ -2049,6 +2050,16 @@ void reset(); }; +#if _LIBCPP_STD_VER >= 17 + +template +packaged_task(_Rp(*)(_Args...)) -> packaged_task<_Rp(_Args...)>; + +template ::type> +packaged_task(_Fp) -> packaged_task<_Stripped>; + +#endif + template void packaged_task::operator()(_ArgTypes... __args) diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1389,6 +1389,7 @@ 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 --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -676,6 +676,7 @@ #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 --- /dev/null +++ b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.compile.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// checks that CTAD works properly + +#include +#include + +int func(char*); +static_assert(std::is_same_v>); + +int funcn(char*) noexcept; +static_assert(std::is_same_v>); + +template +struct Callable { + int operator()(char*) noexcept(Noexcept); +}; +static_assert(std::is_same_v{}}), std::packaged_task>); +static_assert(std::is_same_v{}}), std::packaged_task>); + +template +struct CallableC { + int operator()(char*) const noexcept(Noexcept); +}; +static_assert(std::is_same_v{}}), std::packaged_task>); +static_assert(std::is_same_v{}}), std::packaged_task>); + +template +struct CallableV { + int operator()(char*) const noexcept(Noexcept); +}; +static_assert(std::is_same_v{}}), std::packaged_task>); +static_assert(std::is_same_v{}}), std::packaged_task>); + +template +struct CallableCV { + int operator()(char*) const volatile noexcept(Noexcept); +}; +static_assert(std::is_same_v{}}), std::packaged_task>); +static_assert(std::is_same_v{}}), std::packaged_task>); + +template +struct CallableL { + int operator()(char*) & noexcept(Noexcept); +}; +static_assert(std::is_same_v{}}), std::packaged_task>); +static_assert(std::is_same_v{}}), std::packaged_task>); + +template +struct CallableCL { + int operator()(char*) const & noexcept(Noexcept); +}; +static_assert(std::is_same_v{}}), std::packaged_task>); +static_assert(std::is_same_v{}}), std::packaged_task>); + +template +struct CallableVL { + int operator()(char*) const noexcept(Noexcept); +}; +static_assert(std::is_same_v{}}), std::packaged_task>); +static_assert(std::is_same_v{}}), std::packaged_task>); + +template +struct CallableCVL { + int operator()(char*) const volatile & noexcept(Noexcept); +}; +static_assert(std::is_same_v{}}), std::packaged_task>); +static_assert(std::is_same_v{}}), std::packaged_task>); 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 --- /dev/null +++ b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctad.static.compile.pass.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: (c++17 || c++20) && !stdlib=libc++ +// ADDITIONAL_COMPILE_FLAGS: -Wno-c++2b-extensions + +// checks that CTAD for std::packaged_task works properly with static operator() overloads + +#include +#include + +#if defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L + +struct Except { + static int operator()(int*, long*) { return 0; } +}; +static_assert(std::is_same_v>); + +struct Noexcept { + static int operator()(int*, long*) noexcept { return 0; } +}; +static_assert(std::is_same_v>); + +#endif 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 --- /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 + +// checks that CTAD for std::function works properly with static operator() overloads + +#include +#include + +struct Except0 { + static void operator()() {} +}; +static_assert(std::is_same_v>); + +struct Except1 { + static int operator()(int&) { return 0; } +}; +static_assert(std::is_same_v>); + +struct Except2 { + static int operator()(int*, long*) { return 0; } +}; +static_assert(std::is_same_v>); + +struct ExceptD { + static int operator()(int*, long* = nullptr) { return 0; } +}; +static_assert(std::is_same_v>); + +struct Noexcept { + static int operator()(int*, long*) noexcept { return 0; } +}; + +static_assert(std::is_same_v>);