C++ std::invoke 工具使用

std::invoke 是 C++17 引入的一个标准库函数,用于调用可调用对象,它一般用于模板中,能够以一致的方式处理不同类型的可调用对象。

  • _Functor: 普通函数对象或 lambda。
  • _Pmf_object: 通过对象调用成员函数
  • _Pmf_pointer:通过对象指针调用成员函数
  • _Pmd_object: 通过对象访问成员数据
  • _Pmd_pointer:通过对象指针访问成员数据
  • _Pmd_refwrap:引用包装的成员数据指针,通过 reference_wrapper 访问。
  • _Pmf_refwrap:引用包装的成员函数指针,通过 reference_wrapper 调用。

_template <class _Callable, class _Ty1, class... _Types2>
constexpr auto invoke(_Callable&& _Obj, _Ty1&& _Arg1, _Types2&&... _Args2) 

    noexcept(
        noexcept(_Invoker1<_Callable, _Ty1>::_Call(
            static_cast<_Callable&&>(_Obj), 
            static_cast<_Ty1&&>(_Arg1), 
            static_cast<_Types2&&>(_Args2)...)
        )
    )

    -> decltype(_Invoker1<_Callable, _Ty1>::_Call(
        static_cast<_Callable&&>(_Obj), 
        static_cast<_Ty1&&>(_Arg1), 
        static_cast<_Types2&&>(_Args2)...)
    ) 

{
    
    if constexpr (_Invoker1<_Callable, _Ty1>::_Strategy == _Invoker_strategy::_Functor) 
    {
        return static_cast<_Callable&&>(_Obj)(static_cast<_Ty1&&>(_Arg1), static_cast<_Types2&&>(_Args2)...);
    } 

    else if constexpr (_Invoker1<_Callable, _Ty1>::_Strategy == _Invoker_strategy::_Pmf_object) 
    {
        return (static_cast<_Ty1&&>(_Arg1).*_Obj)(static_cast<_Types2&&>(_Args2)...);
    } 

    else if constexpr (_Invoker1<_Callable, _Ty1>::_Strategy == _Invoker_strategy::_Pmf_refwrap) 
    {
        return (_Arg1.get().*_Obj)(static_cast<_Types2&&>(_Args2)...);
    } 

    else if constexpr (_Invoker1<_Callable, _Ty1>::_Strategy == _Invoker_strategy::_Pmf_pointer) 
    {
        return ((*static_cast<_Ty1&&>(_Arg1)).*_Obj)(static_cast<_Types2&&>(_Args2)...);
    } 

    else if constexpr (_Invoker1<_Callable, _Ty1>::_Strategy == _Invoker_strategy::_Pmd_object) 
    {
        return static_cast<_Ty1&&>(_Arg1).*_Obj;
    } 

    else if constexpr (_Invoker1<_Callable, _Ty1>::_Strategy == _Invoker_strategy::_Pmd_refwrap)
    {

        #if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1956799
                return _Arg1.get().*_Obj;
        #else // ^^^ no workaround / workaround vvv
                auto& _Ref = _Arg1.get();
                return _Ref.*_Obj;
        #endif // ^^^ workaround ^^^
    } 

    else 
    {
        _STL_INTERNAL_STATIC_ASSERT(_Invoker1<_Callable, _Ty1>::_Strategy == _Invoker_strategy::_Pmd_pointer);
        return (*static_cast<_Ty1&&>(_Arg1)).*_Obj;
    }
}

template <class _Callable, class _Ty1, class _Removed_cvref>
struct _Invoker1<_Callable, _Ty1, _Removed_cvref, true, false>
    : conditional_t<
        is_same_v<typename _Is_memfunptr<_Removed_cvref>::_Class_type, _Remove_cvref_t<_Ty1>>|| 
        is_base_of_v<typename _Is_memfunptr<_Removed_cvref>::_Class_type, _Remove_cvref_t<_Ty1>>,

         _Invoker_pmf_object,

        conditional_t<_
            // 检查 _Ty1 是否是 std::reference_wrapper 的特化类型
            Is_specialization_v<_Remove_cvref_t<_Ty1>, reference_wrapper>, 
                _Invoker_pmf_refwrap,
                _Invoker_pmf_pointer>> {}; // pointer to member function


template <class _Callable, class _Ty1, class _Removed_cvref>
struct _Invoker1<_Callable, _Ty1, _Removed_cvref, false, true> conditional_t 
    : conditional_t<
        is_same_v<typename _Is_member_object_pointer<_Removed_cvref>::_Class_type, _Remove_cvref_t<_Ty1>>|| 
        is_base_of_v<typename _Is_member_object_pointer<_Removed_cvref>::_Class_type, _Remove_cvref_t<_Ty1>>,
          
        _Invoker_pmd_object,

        conditional_t<
            _Is_specialization_v<_Remove_cvref_t<_Ty1>, reference_wrapper>, 
                _Invoker_pmd_refwrap,
                _Invoker_pmd_pointer>> {}; // pointer to member data


template <class _Callable, class _Ty1, class _Removed_cvref>
struct _Invoker1<_Callable, _Ty1, _Removed_cvref, false, false> : _Invoker_functor {};



template <class _Callable, class _Ty1, class _Removed_cvref = _Remove_cvref_t<_Callable>,
    bool _Is_pmf = is_member_function_pointer_v<_Removed_cvref>,
    bool _Is_pmd = is_member_object_pointer_v<_Removed_cvref>>
struct _Invoker1;

未经允许不得转载:一亩三分地 » C++ std::invoke 工具使用
评论 (0)

2 + 2 =