std::bind 源码阅读(未加工的生肉)

template<class _Tp> struct __is_bind_expression : public false_type {};
template<class _Tp> struct _LIBCPP_TYPE_VIS_ONLY is_bind_expression
    : public __is_bind_expression<typename remove_cv<_Tp>::type > {};

template<class _Tp> struct __is_placeholder : public integral_constant< int, 0> {};
template<class _Tp> struct _LIBCPP_TYPE_VIS_ONLY is_placeholder
    : public __is_placeholder<typename remove_cv<_Tp>::type > {};

首先是 is_bind_expression 和 is_placeholder. 从这里看 is_bind_expression 会把 cv qualifier 去掉然后返回 false_type. 我猜测会有其他的 is_bind_expression 模板在其他地方定义。

namespace placeholders
{

template < int _Np> struct __ph {};

_LIBCPP_FUNC_VIS extern __ph <1>    _1;
_LIBCPP_FUNC_VIS extern __ph <2>    _2;
_LIBCPP_FUNC_VIS extern __ph <3>    _3;
_LIBCPP_FUNC_VIS extern __ph <4>    _4;
_LIBCPP_FUNC_VIS extern __ph <5>    _5;
_LIBCPP_FUNC_VIS extern __ph <6>    _6;
_LIBCPP_FUNC_VIS extern __ph <7>    _7;
_LIBCPP_FUNC_VIS extern __ph <8>    _8;
_LIBCPP_FUNC_VIS extern __ph <9>    _9;
_LIBCPP_FUNC_VIS extern __ph <10> _10;

}  // placeholders

从这里看起来 placeholder 不是 integral_constant 啊。

template<int _Np>
struct __is_placeholder<placeholders::__ph <_Np> >
    : public integral_constant<int, _Np > {};
前面猜中了。is_placeholder 有另外一个针对 place_holder(ph) 的特化。它的 value type 是 1~10.

reference_wrapper:

reference_wrapper 继承自 __weak_result_type, 前面说过 weak_result_type 用来把函数的引用、指针、无修饰 变成 无修饰 的形式。

    _LIBCPP_INLINE_VISIBILITY reference_wrapper (type& __f) _NOEXCEPT
        : __f_( _VSTD::addressof (__f)) {}

这里的 addressof 获取 __f 的真实地址,甚至在 __f 重载了 & 操作符的情况下。
提供了一个 operator(),其返回值类型是 __invoke_of<type&, _ArgTypes...>::type

    // invoke
    template <class... _ArgTypes>
       _LIBCPP_INLINE_VISIBILITY
       typename __invoke_of<type&, _ArgTypes ...>::type
          operator() (_ArgTypes&&... __args) const
          {
              return __invoke(get(), _VSTD::forward<_ArgTypes>(__args )...);
          }

__invoke_of 在 type_trait.

template < class _Fp, class ..._Args>
struct __invoke_of
    : public __invoke_of_imp<__invokable<_Fp , _Args...>:: value, _Fp , _Args...>
{
};

首先判断是否 invokeable. 如果是,返回 invokable_imp::type.

invokable_impl::typedecltype(__invoke(Fp, Args...)) 的类型。

template < class _Fp, class ..._Args>
struct __invokable
    : public integral_constant<bool,
          __invokable_imp <_Fp, _Args...>::value >
{
};

template < class _Fp, class ..._Args>
struct __invokable_imp
    : private __check_complete<_Fp>
{
    typedef decltype(
            __invoke (_VSTD:: declval<_Fp >(), _VSTD:: declval<_Args >()...)
                    ) type;
    static const bool value = ! is_same<type , __nat>:: value;
};

可以看到 __invokable_imp 首先检查 Fp 是否是 complete type. 如果不是,直接 static_assert 报错。
然后检查 __invoke 的类型是否是 __nat. __nat 是 __invoke(Fp, Args...) 的类型,__invoke 调用 f(args...), 并且如果不能 invoke, fall back 成: __nat

// fall back - none of the bullets

template < class ... _Args>
auto
__invoke(__any , _Args&& ...__args)
    -> __nat ;

注意到这个函数不需要函数体,因为根本不会取到地址。

接着的布尔值返回是否 invokable. 所以:__invokable 是 invoke(Fp, Args...) 是否可调用的结果。 invoke 可调用,返回 true, 否则返回 false。

接着 invoke_of_impl. 返回

template < bool _Invokable, class _Fp , class ..._Args>
struct __invoke_of_imp  // false
{
};

template < class _Fp, class ..._Args>
struct __invoke_of_imp<true, _Fp , _Args...>
{
    typedef typename __invokable_imp<_Fp, _Args ...>::type type;
};

可以看到,如果 invokable, 其 type 就是 invoke(Fp, Args...) 的返回值类型,否则,里面压根没东西(false), 所以比方说 invoke_of 之流会触发 Substitution failure
关于 invoke_of 和 invokable 的来历参见:__function_base

__invoke, 分别对 成员函数、成员函数指针、成员函数指针(caller 是指针)成员变量、成员变量(caller 是指针),以及其他函数做特化。一共五个 bullet.

回去看 reference_wrapper, 可以发现 如果 Tp not invokable, 那么 invoke_of 会 fail, 导致 operator () subsitution failed. 否则operator() 返回 invoke(f, args...)
reference_wrapper 对f 取指针,保证了在 f not copiable 的时候正常工作。

template < class _Tp, class _Uj>
inline _LIBCPP_INLINE_VISIBILITY
_Tp&
__mu(reference_wrapper <_Tp> __t, _Uj &)
{
    return __t .get();
}

所以 __mu 返回 Tp t, 保证不对 t 做拷贝、move 或者其他操作。

template < class _Ti, class ..._Uj, size_t ..._Indx>
inline _LIBCPP_INLINE_VISIBILITY
typename __invoke_of<_Ti&, _Uj ...>::type
__mu_expand(_Ti & __ti, tuple<_Uj ...>& __uj, __tuple_indices<_Indx ...>)
{
    return __ti (_VSTD:: forward<_Uj >(_VSTD:: get<_Indx >(__uj))...);
}

__mu_expand 根据 indices get<index>(uj). 然后调用 ti(Args...) 再次注意这里的 invoke_of 保证了这个函数被自 enable。

template < class _Ti, class ..._Uj>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if
<
    is_bind_expression <_Ti>:: value,
    typename __invoke_of <_Ti&, _Uj...>::type
>::type
__mu(_Ti & __ti, tuple<_Uj ...>& __uj)
{
    typedef typename __make_tuple_indices<sizeof ...(_Uj)>:: type __indices;
    return  __mu_expand (__ti, __uj, __indices ());
}

如果 Ti 是 bind_expression 那么 enable,返回值是__invoke_if< Ti, Uj...>
make_tuple_indoces通过逐个递归返回 tuple<...>

实现如下:

template < size_t...> struct __tuple_indices {};

template < size_t _Sp, class _IntTuple, size_t _Ep>
struct __make_indices_imp;

template < size_t _Sp, size_t ..._Indices, size_t _Ep>
struct __make_indices_imp<_Sp, __tuple_indices <_Indices...>, _Ep>
{
    typedef typename __make_indices_imp<_Sp+1 , __tuple_indices< _Indices..., _Sp >, _Ep>:: type type;
};

template < size_t _Ep, size_t ..._Indices>
struct __make_indices_imp<_Ep, __tuple_indices <_Indices...>, _Ep>
{
    typedef __tuple_indices <_Indices...> type;
};

template < size_t _Ep, size_t _Sp = 0 >
struct __make_tuple_indices
{
    static_assert(_Sp <= _Ep , "__make_tuple_indices input error" );
    typedef typename __make_indices_imp<_Sp, __tuple_indices <>, _Ep>::type type;
};

mu_return2 返回对应位置的类型,如果对应位置是 placeholder. 否则 disable。

template < bool IsPh, class _Ti, class _Uj>
struct __mu_return2 {};

template < class _Ti, class _Uj>
struct __mu_return2<true, _Ti , _Uj>
{
    typedef typename tuple_element<is_placeholder<_Ti >::value - 1 , _Uj>::type type;
};

template < class _Ti, class _Uj>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if
<
    0 < is_placeholder <_Ti>:: value,
    typename __mu_return2 <0 < is_placeholder <_Ti>:: value, _Ti , _Uj>::type
>::type
__mu(_Ti &, _Uj& __uj)
{
    const size_t _Indx = is_placeholder<_Ti>::value - 1 ;
    return _VSTD ::forward<typename tuple_element<_Indx, _Uj>::type>( _VSTD::get <_Indx>( __uj));
}

如果 Ti 是 placeholder,那么返回 Uj 在对应 index 的类型以及值。

template < class _Ti, class _Uj>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if
<
    !is_bind_expression <_Ti>:: value &&
    is_placeholder<_Ti >::value == 0 &&
    !__is_reference_wrapper <_Ti>:: value,
    _Ti&
>::type
__mu(_Ti & __ti, _Uj&)
{
    return __ti ;
}

如果既不是 placeholder, 也不是 bind_expression, 也不是 reference_wrapper, 直接返回 Ti.

template < class _Ti, bool IsReferenceWrapper, bool IsBindEx, bool IsPh ,
          class _TupleUj>
struct ____mu_return;

三个条件,RefWrapper, BindExp, Placeholder, 用来返回某个 Ti 的返回类型。

_is_valid_bind_return 用来判断 bind 是否 invokable. 注意看这里的用法:

__invokable<_Fp , typename __mu_return<const _BoundArgs, _TupleUj>::type...>::value;

Leave a Reply

Your email address will not be published. Required fields are marked *