mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 13:16:46 +00:00
[libc++] Implement P1169R4 (static operator())
Reviewed By: ldionne, huixie90, #libc Spies: EricWF, libcxx-commits, royjacobson Differential Revision: https://reviews.llvm.org/D135016
This commit is contained in:
parent
d2cbdb6bef
commit
3ec6c997c6
@ -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
|
||||
-----------------------------
|
||||
|
@ -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"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -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","",""
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -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
|
||||
|
@ -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 @@ public:
|
||||
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
|
||||
|
79
libcxx/include/__type_traits/strip_signature.h
Normal file
79
libcxx/include/__type_traits/strip_signature.h
Normal file
@ -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
|
@ -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)
|
||||
|
@ -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" }
|
||||
|
@ -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'}}
|
||||
|
@ -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*)>>);
|
@ -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*)>>);
|
@ -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*)>>);
|
Loading…
x
Reference in New Issue
Block a user