Skip to content

Commit a5b5248

Browse files
authored
[libc++] Simplify std::function implementation further (#145153)
We can use `if constexpr` and `__is_invocable_r` to simplify the `function` implementation a bit.
1 parent 4a2dd31 commit a5b5248

File tree

2 files changed

+60
-72
lines changed

2 files changed

+60
-72
lines changed

libcxx/include/__functional/function.h

Lines changed: 54 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,14 @@
1515
#include <__cstddef/nullptr_t.h>
1616
#include <__exception/exception.h>
1717
#include <__functional/binary_function.h>
18-
#include <__functional/invoke.h>
1918
#include <__functional/unary_function.h>
2019
#include <__memory/addressof.h>
2120
#include <__type_traits/aligned_storage.h>
2221
#include <__type_traits/decay.h>
23-
#include <__type_traits/is_core_convertible.h>
22+
#include <__type_traits/invoke.h>
2423
#include <__type_traits/is_scalar.h>
2524
#include <__type_traits/is_trivially_constructible.h>
2625
#include <__type_traits/is_trivially_destructible.h>
27-
#include <__type_traits/is_void.h>
2826
#include <__type_traits/strip_signature.h>
2927
#include <__utility/forward.h>
3028
#include <__utility/move.h>
@@ -95,29 +93,29 @@ template <class _Rp, class _A1, class _A2>
9593
struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)> : public __binary_function<_A1, _A2, _Rp> {};
9694

9795
template <class _Fp>
98-
_LIBCPP_HIDE_FROM_ABI bool __not_null(_Fp const&) {
99-
return true;
96+
_LIBCPP_HIDE_FROM_ABI bool __is_null(_Fp const&) {
97+
return false;
10098
}
10199

102100
template <class _Fp>
103-
_LIBCPP_HIDE_FROM_ABI bool __not_null(_Fp* __ptr) {
104-
return __ptr;
101+
_LIBCPP_HIDE_FROM_ABI bool __is_null(_Fp* __ptr) {
102+
return !__ptr;
105103
}
106104

107105
template <class _Ret, class _Class>
108-
_LIBCPP_HIDE_FROM_ABI bool __not_null(_Ret _Class::*__ptr) {
109-
return __ptr;
106+
_LIBCPP_HIDE_FROM_ABI bool __is_null(_Ret _Class::* __ptr) {
107+
return !__ptr;
110108
}
111109

112110
template <class _Fp>
113-
_LIBCPP_HIDE_FROM_ABI bool __not_null(function<_Fp> const& __f) {
114-
return !!__f;
111+
_LIBCPP_HIDE_FROM_ABI bool __is_null(function<_Fp> const& __f) {
112+
return !__f;
115113
}
116114

117115
# if __has_extension(blocks)
118116
template <class _Rp, class... _Args>
119-
_LIBCPP_HIDE_FROM_ABI bool __not_null(_Rp (^__p)(_Args...)) {
120-
return __p;
117+
_LIBCPP_HIDE_FROM_ABI bool __is_null(_Rp (^__p)(_Args...)) {
118+
return !__p;
121119
}
122120
# endif
123121

@@ -206,12 +204,13 @@ class __value_func<_Rp(_ArgTypes...)> {
206204
_LIBCPP_HIDE_FROM_ABI explicit __value_func(_Fp&& __f) : __f_(nullptr) {
207205
typedef __function::__func<_Fp, _Rp(_ArgTypes...)> _Fun;
208206

209-
if (__function::__not_null(__f)) {
210-
if (sizeof(_Fun) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value) {
211-
__f_ = ::new (std::addressof(__buf_)) _Fun(std::move(__f));
212-
} else {
213-
__f_ = new _Fun(std::move(__f));
214-
}
207+
if (__function::__is_null(__f))
208+
return;
209+
210+
if (sizeof(_Fun) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value) {
211+
__f_ = ::new (std::addressof(__buf_)) _Fun(std::move(__f));
212+
} else {
213+
__f_ = new _Fun(std::move(__f));
215214
}
216215
}
217216

@@ -356,7 +355,31 @@ struct __policy {
356355
// type.
357356
template <typename _Fun>
358357
_LIBCPP_HIDE_FROM_ABI static const __policy* __create() {
359-
return __choose_policy<_Fun>(__use_small_storage<_Fun>());
358+
if constexpr (__use_small_storage<_Fun>::value) {
359+
static constexpr __policy __policy = {
360+
nullptr,
361+
nullptr,
362+
false,
363+
# if _LIBCPP_HAS_RTTI
364+
&typeid(_Fun)
365+
# else
366+
nullptr
367+
# endif
368+
};
369+
return &__policy;
370+
} else {
371+
static constexpr __policy __policy = {
372+
std::addressof(__large_clone<_Fun>),
373+
std::addressof(__large_destroy<_Fun>),
374+
false,
375+
# if _LIBCPP_HAS_RTTI
376+
&typeid(_Fun)
377+
# else
378+
nullptr
379+
# endif
380+
};
381+
return &__policy;
382+
}
360383
}
361384

362385
_LIBCPP_HIDE_FROM_ABI static const __policy* __create_empty() {
@@ -384,36 +407,6 @@ struct __policy {
384407
_LIBCPP_HIDE_FROM_ABI static void __large_destroy(void* __s) {
385408
delete static_cast<_Fun*>(__s);
386409
}
387-
388-
template <typename _Fun>
389-
_LIBCPP_HIDE_FROM_ABI static const __policy* __choose_policy(/* is_small = */ false_type) {
390-
static constexpr __policy __policy = {
391-
std::addressof(__large_clone<_Fun>),
392-
std::addressof(__large_destroy<_Fun>),
393-
false,
394-
# if _LIBCPP_HAS_RTTI
395-
&typeid(_Fun)
396-
# else
397-
nullptr
398-
# endif
399-
};
400-
return &__policy;
401-
}
402-
403-
template <typename _Fun>
404-
_LIBCPP_HIDE_FROM_ABI static const __policy* __choose_policy(/* is_small = */ true_type) {
405-
static constexpr __policy __policy = {
406-
nullptr,
407-
nullptr,
408-
false,
409-
# if _LIBCPP_HAS_RTTI
410-
&typeid(_Fun)
411-
# else
412-
nullptr
413-
# endif
414-
};
415-
return &__policy;
416-
}
417410
};
418411

419412
// Used to choose between perfect forwarding or pass-by-value. Pass-by-value is
@@ -455,14 +448,15 @@ class __policy_func<_Rp(_ArgTypes...)> {
455448

456449
template <class _Fp, __enable_if_t<!is_same<__decay_t<_Fp>, __policy_func>::value, int> = 0>
457450
_LIBCPP_HIDE_FROM_ABI explicit __policy_func(_Fp&& __f) : __policy_(__policy::__create_empty()) {
458-
if (__function::__not_null(__f)) {
459-
__func_ = __call_func<_Fp>;
460-
__policy_ = __policy::__create<_Fp>();
461-
if (__use_small_storage<_Fp>()) {
462-
::new ((void*)&__buf_.__small) _Fp(std::move(__f));
463-
} else {
464-
__buf_.__large = ::new _Fp(std::move(__f));
465-
}
451+
if (__function::__is_null(__f))
452+
return;
453+
454+
__func_ = __call_func<_Fp>;
455+
__policy_ = __policy::__create<_Fp>();
456+
if (__use_small_storage<_Fp>()) {
457+
::new ((void*)&__buf_.__small) _Fp(std::move(__f));
458+
} else {
459+
__buf_.__large = ::new _Fp(std::move(__f));
466460
}
467461
}
468462

@@ -615,21 +609,9 @@ class function<_Rp(_ArgTypes...)>
615609

616610
__func __f_;
617611

618-
template <class _Fp,
619-
bool = _And<_IsNotSame<__remove_cvref_t<_Fp>, function>, __is_invocable<_Fp, _ArgTypes...> >::value>
620-
struct __callable;
621-
template <class _Fp>
622-
struct __callable<_Fp, true> {
623-
static const bool value =
624-
is_void<_Rp>::value || __is_core_convertible<__invoke_result_t<_Fp, _ArgTypes...>, _Rp>::value;
625-
};
626-
template <class _Fp>
627-
struct __callable<_Fp, false> {
628-
static const bool value = false;
629-
};
630-
631612
template <class _Fp>
632-
using _EnableIfLValueCallable _LIBCPP_NODEBUG = __enable_if_t<__callable<_Fp&>::value>;
613+
using _EnableIfLValueCallable _LIBCPP_NODEBUG = __enable_if_t<
614+
_And<_IsNotSame<__remove_cvref_t<_Fp>, function>, __is_invocable_r<_Rp, _Fp&, _ArgTypes...>>::value>;
633615

634616
public:
635617
typedef _Rp result_type;

libcxx/include/__type_traits/invoke.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@
6262
//
6363
// template <class Func, class... Args>
6464
// using __invoke_result_t = invoke_result_t<Func, Args...>;
65+
//
66+
// template <class Ret, class Func, class... Args>
67+
// struct __is_invocable_r : is_invocable_r<Ret, Func, Args...> {};
6568

6669
_LIBCPP_BEGIN_NAMESPACE_STD
6770

@@ -329,6 +332,9 @@ using __invoke_result_t _LIBCPP_NODEBUG = typename __invoke_result<_Func, _Args.
329332

330333
#endif // __has_builtin(__builtin_invoke_r)
331334

335+
template <class _Ret, class _Func, class... _Args>
336+
struct __is_invocable_r : integral_constant<bool, __is_invocable_r_v<_Ret, _Func, _Args...> > {};
337+
332338
template <class _Ret, bool = is_void<_Ret>::value>
333339
struct __invoke_void_return_wrapper {
334340
template <class... _Args>

0 commit comments

Comments
 (0)