• std::apply 源码分析


    std::apply 源码分析

    背景:

    std::apply 适合感觉跟std::invoke 有点相似, 前边参数是可以调用的对象, 后边是一个tuple类型,在做线程的任务包装的时候,可以使用这个apply,

    接下来我们就看下它的源码

    std::apply 用例

    C++
    #include
    #include
    #include <utility>
     
    int add(int first, int second) { return first + second; }
     
    template
    T add_generic(T first, T second) { return first + second; }
     
    auto add_lambda = [](auto first, auto second) { return first + second; };
     
    template
    std::ostream& operator<<(std::ostream& os, std::tuple const& theTuple)
    {
        std::apply
        (
            [&os](Ts const&... tupleArgs)
            {
                os << '[';
                std::size_t n{0};
                ((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...);
                os << ']';
            }, theTuple
        );
        return os;
    }
     
    int main()
    {
        // OK
        std::cout << std::apply(add, std::pair(1, 2)) << '\n';
     
        // Error: can't deduce the function type
        // std::cout << std::apply(add_generic, std::make_pair(2.0f, 3.0f)) << '\n';
     
        // OK
        std::cout << std::apply(add_lambda, std::pair(2.0f, 3.0f)) << '\n';
     
        // advanced example
        std::tuple myTuple{25, "Hello", 9.31f, 'c'};
        std::cout << myTuple << '\n';
    }

    https://en.cppreference.com/w/cpp/utility/apply

    Output

    C++
    3
    5
    [25, Hello, 9.31, c]

    std::apply 源码

    C++
    template
    inline _LIBCPP_INLINE_VISIBILITY
    constexpr decltype(auto) apply(_Fn && __f, _Tuple && __t)
    _LIBCPP_NOEXCEPT_RETURN(
        _VSTD::__apply_tuple_impl(
            _VSTD::forward<_Fn>(__f), _VSTD::forward<_Tuple>(__t),
            typename __make_tuple_indices>>::type{})
    )

    这个跟std::make_from_tuple基本上一样,请移步到https://blog.csdn.net/c553110519/article/details/126838742

    汇编

    C++
    int TestApply(int a, int b)
    {
        return a + b;
    }
    void Test()
    {
       int sum = std::apply(TestApply, std::tuple(1,2));
        std::cout< }

    Assembly language
        0x1000036f0 <+0>:   sub    sp, sp, #0x30
        0x1000036f4 <+4>:   stp    x20, x19, [sp, #0x10]
        0x1000036f8 <+8>:   stp    x29, x30, [sp, #0x20]
        0x1000036fc <+12>:  add    x29, sp, #0x20
        0x100003700 <+16>:  nop   
        0x100003704 <+20>:  ldr    x0, #0x93c                ; (void *)0x00000001fd11dd98: std::__1::cout
        0x100003708 <+24>:  mov    w1, #0x3
        0x10000370c <+28>:  bl     0x100003c94               ; symbol stub for: std::__1::basic_ostream >::operator<<(int)
     

    可以看的出来最终转成sum = std::apply(TestApply, std::tuple(1,2));汇编后mov    w1, #0x3,编译器把中间过程给做了,丝毫没有影响到性能,constexpr的特性所致

  • 相关阅读:
    基于神经网络的系统辨识,神经网络的种类和特点
    Java替换RequestBody和RequestParam参数的属性
    少年,不知道怎么在安卓中使用 PaddleOCR ?看我怎么把它二次封装成只需要两行代码即可使用
    2022年高教社杯国赛C题 | 古代玻璃制品的成分分析与鉴别(Matlab实现)
    HTML的特殊字符
    【设计模式】原型模式
    微服务框架 SpringCloud微服务架构 16 SpringAMQP 16.8 TopicExchange
    Android 11 AudioPolicyService 启动流程
    哪种品牌台灯适合学生用?盘点学生护眼台灯十大牌子
    4.jvm入门到精通
  • 原文地址:https://blog.csdn.net/c553110519/article/details/126840102