Use INVOKE<R> in std::function, std::bind and std::packaged_task
As well as simpifying the code by removing duplication, this means that we only need to touch std::__invoke_r if we need to implement changes to INVOKE<R>, such as those in P0932R0. * include/bits/std_function.h (_Simple_type_wrapper): Remove. (_Function_handler): Remove partial specializations for void return types and pointers to member. (_Function_handler::_M_manager): Adapt to removal of _Simple_type_wrapper. (_Function_handler::_M_invoke): Use __invoke_r instead of __invoke. * include/std/functional (_Bind_result::__enable_if_void) (_Bind_result::__disable_if_void): Remove sfinae helpers. (_Bind_result::__call): Use __invoke_r and remove overloads for void return types. * include/std/future (__future_base::_Task_state::_M_run) (__future_base::_Task_state::_M_run_delayed): Use __invoke_r and change return type of lambda expressions. From-SVN: r271174
This commit is contained in:
parent
78c2855df6
commit
330b17474c
@ -1,5 +1,19 @@
|
||||
2019-05-14 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/bits/std_function.h (_Simple_type_wrapper): Remove.
|
||||
(_Function_handler): Remove partial specializations for void return
|
||||
types and pointers to member.
|
||||
(_Function_handler::_M_manager): Adapt to removal of
|
||||
_Simple_type_wrapper.
|
||||
(_Function_handler::_M_invoke): Use __invoke_r instead of __invoke.
|
||||
* include/std/functional (_Bind_result::__enable_if_void)
|
||||
(_Bind_result::__disable_if_void): Remove sfinae helpers.
|
||||
(_Bind_result::__call): Use __invoke_r and remove overloads for void
|
||||
return types.
|
||||
* include/std/future (__future_base::_Task_state::_M_run)
|
||||
(__future_base::_Task_state::_M_run_delayed): Use __invoke_r and
|
||||
change return type of lambda expressions.
|
||||
|
||||
* include/bits/invoke.h (__invoke_r): Define new function implementing
|
||||
the INVOKE<R> pseudo-function.
|
||||
* testsuite/20_util/function_objects/invoke/1.cc: Add more tests.
|
||||
|
@ -109,21 +109,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
__destroy_functor
|
||||
};
|
||||
|
||||
// Simple type wrapper that helps avoid annoying const problems
|
||||
// when casting between void pointers and pointers-to-pointers.
|
||||
template<typename _Tp>
|
||||
struct _Simple_type_wrapper
|
||||
{
|
||||
_Simple_type_wrapper(_Tp __value) : __value(__value) { }
|
||||
|
||||
_Tp __value;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_location_invariant<_Simple_type_wrapper<_Tp> >
|
||||
: __is_location_invariant<_Tp>
|
||||
{ };
|
||||
|
||||
template<typename _Signature>
|
||||
class function;
|
||||
|
||||
@ -278,56 +263,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{
|
||||
typedef _Function_base::_Base_manager<_Functor> _Base;
|
||||
|
||||
public:
|
||||
static _Res
|
||||
_M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
|
||||
{
|
||||
return (*_Base::_M_get_pointer(__functor))(
|
||||
std::forward<_ArgTypes>(__args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Functor, typename... _ArgTypes>
|
||||
class _Function_handler<void(_ArgTypes...), _Functor>
|
||||
: public _Function_base::_Base_manager<_Functor>
|
||||
{
|
||||
typedef _Function_base::_Base_manager<_Functor> _Base;
|
||||
|
||||
public:
|
||||
static void
|
||||
_M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
|
||||
{
|
||||
(*_Base::_M_get_pointer(__functor))(
|
||||
std::forward<_ArgTypes>(__args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Class, typename _Member, typename _Res,
|
||||
typename... _ArgTypes>
|
||||
class _Function_handler<_Res(_ArgTypes...), _Member _Class::*>
|
||||
: public _Function_handler<void(_ArgTypes...), _Member _Class::*>
|
||||
{
|
||||
typedef _Function_handler<void(_ArgTypes...), _Member _Class::*>
|
||||
_Base;
|
||||
|
||||
public:
|
||||
static _Res
|
||||
_M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
|
||||
{
|
||||
return std::__invoke(_Base::_M_get_pointer(__functor)->__value,
|
||||
std::forward<_ArgTypes>(__args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Class, typename _Member, typename... _ArgTypes>
|
||||
class _Function_handler<void(_ArgTypes...), _Member _Class::*>
|
||||
: public _Function_base::_Base_manager<
|
||||
_Simple_type_wrapper< _Member _Class::* > >
|
||||
{
|
||||
typedef _Member _Class::* _Functor;
|
||||
typedef _Simple_type_wrapper<_Functor> _Wrapper;
|
||||
typedef _Function_base::_Base_manager<_Wrapper> _Base;
|
||||
|
||||
public:
|
||||
static bool
|
||||
_M_manager(_Any_data& __dest, const _Any_data& __source,
|
||||
@ -341,8 +276,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
break;
|
||||
#endif
|
||||
case __get_functor_ptr:
|
||||
__dest._M_access<_Functor*>() =
|
||||
&_Base::_M_get_pointer(__source)->__value;
|
||||
__dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -351,11 +285,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
static _Res
|
||||
_M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
|
||||
{
|
||||
std::__invoke(_Base::_M_get_pointer(__functor)->__value,
|
||||
std::forward<_ArgTypes>(__args)...);
|
||||
return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor),
|
||||
std::forward<_ArgTypes>(__args)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -539,89 +539,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
_Functor _M_f;
|
||||
tuple<_Bound_args...> _M_bound_args;
|
||||
|
||||
// sfinae types
|
||||
template<typename _Res>
|
||||
using __enable_if_void
|
||||
= typename enable_if<is_void<_Res>{}>::type;
|
||||
|
||||
template<typename _Res>
|
||||
using __disable_if_void
|
||||
= typename enable_if<!is_void<_Res>{}, _Result>::type;
|
||||
|
||||
// Call unqualified
|
||||
template<typename _Res, typename... _Args, std::size_t... _Indexes>
|
||||
__disable_if_void<_Res>
|
||||
_Res
|
||||
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
|
||||
{
|
||||
return std::__invoke(_M_f, _Mu<_Bound_args>()
|
||||
return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>()
|
||||
(std::get<_Indexes>(_M_bound_args), __args)...);
|
||||
}
|
||||
|
||||
// Call unqualified, return void
|
||||
template<typename _Res, typename... _Args, std::size_t... _Indexes>
|
||||
__enable_if_void<_Res>
|
||||
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
|
||||
{
|
||||
std::__invoke(_M_f, _Mu<_Bound_args>()
|
||||
(std::get<_Indexes>(_M_bound_args), __args)...);
|
||||
}
|
||||
|
||||
// Call as const
|
||||
template<typename _Res, typename... _Args, std::size_t... _Indexes>
|
||||
__disable_if_void<_Res>
|
||||
_Res
|
||||
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const
|
||||
{
|
||||
return std::__invoke(_M_f, _Mu<_Bound_args>()
|
||||
return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>()
|
||||
(std::get<_Indexes>(_M_bound_args), __args)...);
|
||||
}
|
||||
|
||||
// Call as const, return void
|
||||
template<typename _Res, typename... _Args, std::size_t... _Indexes>
|
||||
__enable_if_void<_Res>
|
||||
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const
|
||||
{
|
||||
std::__invoke(_M_f, _Mu<_Bound_args>()
|
||||
(std::get<_Indexes>(_M_bound_args), __args)...);
|
||||
}
|
||||
|
||||
// Call as volatile
|
||||
template<typename _Res, typename... _Args, std::size_t... _Indexes>
|
||||
__disable_if_void<_Res>
|
||||
_Res
|
||||
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile
|
||||
{
|
||||
return std::__invoke(_M_f, _Mu<_Bound_args>()
|
||||
return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>()
|
||||
(__volget<_Indexes>(_M_bound_args), __args)...);
|
||||
}
|
||||
|
||||
// Call as volatile, return void
|
||||
template<typename _Res, typename... _Args, std::size_t... _Indexes>
|
||||
__enable_if_void<_Res>
|
||||
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile
|
||||
{
|
||||
std::__invoke(_M_f, _Mu<_Bound_args>()
|
||||
(__volget<_Indexes>(_M_bound_args), __args)...);
|
||||
}
|
||||
|
||||
// Call as const volatile
|
||||
template<typename _Res, typename... _Args, std::size_t... _Indexes>
|
||||
__disable_if_void<_Res>
|
||||
_Res
|
||||
__call(tuple<_Args...>&& __args,
|
||||
_Index_tuple<_Indexes...>) const volatile
|
||||
{
|
||||
return std::__invoke(_M_f, _Mu<_Bound_args>()
|
||||
return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>()
|
||||
(__volget<_Indexes>(_M_bound_args), __args)...);
|
||||
}
|
||||
|
||||
// Call as const volatile, return void
|
||||
template<typename _Res, typename... _Args, std::size_t... _Indexes>
|
||||
__enable_if_void<_Res>
|
||||
__call(tuple<_Args...>&& __args,
|
||||
_Index_tuple<_Indexes...>) const volatile
|
||||
{
|
||||
std::__invoke(_M_f, _Mu<_Bound_args>()
|
||||
(__volget<_Indexes>(_M_bound_args), __args)...);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef _Result result_type;
|
||||
|
||||
|
@ -1417,8 +1417,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
virtual void
|
||||
_M_run(_Args&&... __args)
|
||||
{
|
||||
auto __boundfn = [&] () -> typename result_of<_Fn&(_Args&&...)>::type {
|
||||
return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...);
|
||||
auto __boundfn = [&] () -> _Res {
|
||||
return std::__invoke_r<_Res>(_M_impl._M_fn,
|
||||
std::forward<_Args>(__args)...);
|
||||
};
|
||||
this->_M_set_result(_S_task_setter(this->_M_result, __boundfn));
|
||||
}
|
||||
@ -1426,8 +1427,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
virtual void
|
||||
_M_run_delayed(_Args&&... __args, weak_ptr<_State_base> __self)
|
||||
{
|
||||
auto __boundfn = [&] () -> typename result_of<_Fn&(_Args&&...)>::type {
|
||||
return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...);
|
||||
auto __boundfn = [&] () -> _Res {
|
||||
return std::__invoke_r<_Res>(_M_impl._M_fn,
|
||||
std::forward<_Args>(__args)...);
|
||||
};
|
||||
this->_M_set_delayed_result(_S_task_setter(this->_M_result, __boundfn),
|
||||
std::move(__self));
|
||||
|
Loading…
Reference in New Issue
Block a user