在试图理解std::bind
分配内存的条件时,我看了这个答案,它给出了一些直觉,但我想要更详细的理解,所以我去看了gcc
的来源。
我正在研究以下来自C++标准库的gcc实现的std::bind
的源代码。
/**
* @brief Function template for std::bind.
* @ingroup binders
*/
template<typename _Func, typename... _BoundArgs>
inline typename
_Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type
bind(_Func&& __f, _BoundArgs&&... __args)
{
typedef _Bind_helper<false, _Func, _BoundArgs...> __helper_type;
typedef typename __helper_type::__maybe_type __maybe_type;
typedef typename __helper_type::type __result_type;
return __result_type(__maybe_type::__do_wrap(std::forward<_Func>(__f)),
std::forward<_BoundArgs>(__args)...);
}
给定一个函数F和参数a和B,我在哪里可以找到将它们复制到返回的数据结构中的代码,或者这个编译器是生成的?
此行:
__result_type(__maybe_type::__do_wrap(std::forward<_Func>(__f)), std::forward<_BoundArgs>(__args)...);
参数,包括可调用的(用__do_wrap
包装)和自变量,都被转发到__result_type
类型,该类型可能将它们存储在数据结构中。
您应该查找代码__result_type
,它将前者返回的数据封装在上面两行提到的实现定义类型中(即_Bind_helper<false, _Func, _BoundArgs...>::type
)
实际类型是_Bind
(搜索class _Bind
),它有一个接受可调用和参数的构造函数,当然,它是一个模板类(通过一些助手公开)
事实上,Bind_helper<whatever>::type
(即返回的类型)被定义为typedef _Bind<whatever> type
,您可以查找该类,仅此而已。
我们没有在任何地方分配内存。我们只是创建一个类型特定于该特定bind()
的对象,该对象具有一个函数成员(可能封装到其他类型中,并根据情况进行复制/移动)和一个参数的tuple
(根据情况进行拷贝/移动)。
该标准没有指定任何关于内存分配的内容,但没有必要为bind()
做这样的事情,所以任何好的实现都不会。
此过载返回一个:
_Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type
如果__is_socketlike<_Func>::value
是false
,则该过载仅参与过载解决。在这种情况下,这种类型是:
typedef _Maybe_wrap_member_pointer<typename decay<_Func>::type> __maybe_type;
typedef typename __maybe_type::type __func_type;
typedef _Bind<__func_type(typename decay<_BoundArgs>::type...)> type;
忽略模板参数的含义,我们基本上是在构建某种类型的东西:
template<typename _Signature>
struct _Bind;
template<typename _Functor, typename... _Bound_args>
class _Bind<_Functor(_Bound_args...)>
: public _Weak_result_type<_Functor>
{
...
};
拥有以下成员:
_Functor _M_f;
tuple<_Bound_args...> _M_bound_args;
以及这些相关的构造器:
template<typename... _Args>
explicit _Bind(const _Functor& __f, _Args&&... __args)
: _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...)
{ }
template<typename... _Args>
explicit _Bind(_Functor&& __f, _Args&&... __args)
: _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...)
{ }