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:
Jonathan Wakely 2019-05-14 16:25:08 +01:00 committed by Jonathan Wakely
parent 78c2855df6
commit 330b17474c
4 changed files with 32 additions and 128 deletions

View File

@ -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.

View File

@ -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)...);
}
};

View File

@ -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;

View File

@ -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));