Commit 330b1747 by Jonathan Wakely Committed by Jonathan Wakely

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
parent 78c2855d
2019-05-14 Jonathan Wakely <jwakely@redhat.com> 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 * include/bits/invoke.h (__invoke_r): Define new function implementing
the INVOKE<R> pseudo-function. the INVOKE<R> pseudo-function.
* testsuite/20_util/function_objects/invoke/1.cc: Add more tests. * testsuite/20_util/function_objects/invoke/1.cc: Add more tests.
......
...@@ -109,21 +109,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -109,21 +109,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__destroy_functor __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> template<typename _Signature>
class function; class function;
...@@ -279,56 +264,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -279,56 +264,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _Function_base::_Base_manager<_Functor> _Base; typedef _Function_base::_Base_manager<_Functor> _Base;
public: 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 static bool
_M_manager(_Any_data& __dest, const _Any_data& __source, _M_manager(_Any_data& __dest, const _Any_data& __source,
_Manager_operation __op) _Manager_operation __op)
...@@ -341,8 +276,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -341,8 +276,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
break; break;
#endif #endif
case __get_functor_ptr: case __get_functor_ptr:
__dest._M_access<_Functor*>() = __dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source);
&_Base::_M_get_pointer(__source)->__value;
break; break;
default: default:
...@@ -351,10 +285,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -351,10 +285,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return false; return false;
} }
static void static _Res
_M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
{ {
std::__invoke(_Base::_M_get_pointer(__functor)->__value, return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor),
std::forward<_ArgTypes>(__args)...); std::forward<_ArgTypes>(__args)...);
} }
}; };
......
...@@ -539,86 +539,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -539,86 +539,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Functor _M_f; _Functor _M_f;
tuple<_Bound_args...> _M_bound_args; 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 // Call unqualified
template<typename _Res, typename... _Args, std::size_t... _Indexes> 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>()
(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...>) __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
{ {
std::__invoke(_M_f, _Mu<_Bound_args>() return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>()
(std::get<_Indexes>(_M_bound_args), __args)...); (std::get<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const // Call as const
template<typename _Res, typename... _Args, std::size_t... _Indexes> 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>()
(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 __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const
{ {
std::__invoke(_M_f, _Mu<_Bound_args>() return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>()
(std::get<_Indexes>(_M_bound_args), __args)...); (std::get<_Indexes>(_M_bound_args), __args)...);
} }
// Call as volatile // Call as volatile
template<typename _Res, typename... _Args, std::size_t... _Indexes> template<typename _Res, typename... _Args, std::size_t... _Indexes>
__disable_if_void<_Res> _Res
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile __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)...); (__volget<_Indexes>(_M_bound_args), __args)...);
} }
// Call as const volatile // Call as const volatile
template<typename _Res, typename... _Args, std::size_t... _Indexes> 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>()
(__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, __call(tuple<_Args...>&& __args,
_Index_tuple<_Indexes...>) const volatile _Index_tuple<_Indexes...>) const volatile
{ {
std::__invoke(_M_f, _Mu<_Bound_args>() return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>()
(__volget<_Indexes>(_M_bound_args), __args)...); (__volget<_Indexes>(_M_bound_args), __args)...);
} }
......
...@@ -1417,8 +1417,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1417,8 +1417,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
virtual void virtual void
_M_run(_Args&&... __args) _M_run(_Args&&... __args)
{ {
auto __boundfn = [&] () -> typename result_of<_Fn&(_Args&&...)>::type { auto __boundfn = [&] () -> _Res {
return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...); return std::__invoke_r<_Res>(_M_impl._M_fn,
std::forward<_Args>(__args)...);
}; };
this->_M_set_result(_S_task_setter(this->_M_result, __boundfn)); this->_M_set_result(_S_task_setter(this->_M_result, __boundfn));
} }
...@@ -1426,8 +1427,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1426,8 +1427,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
virtual void virtual void
_M_run_delayed(_Args&&... __args, weak_ptr<_State_base> __self) _M_run_delayed(_Args&&... __args, weak_ptr<_State_base> __self)
{ {
auto __boundfn = [&] () -> typename result_of<_Fn&(_Args&&...)>::type { auto __boundfn = [&] () -> _Res {
return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...); 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), this->_M_set_delayed_result(_S_task_setter(this->_M_result, __boundfn),
std::move(__self)); std::move(__self));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment