std::apply 源码分析

std::apply 源码分析

背景:

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

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

std::apply 用例

C++
#include <iostream>
#include <tuple>
#include <utility>
 
int add(int first, int second) { return first + second; }
 
template<typename T>
T add_generic(T first, T second) { return first + second; }
 
auto add_lambda = [](auto first, auto second) { return first + second; };
 
template<typename... Ts>
std::ostream& operator<<(std::ostream& os, std::tuple<Ts...> 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 <class _Fn, class _Tuple>
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<tuple_size_v<remove_reference_t<_Tuple>>>::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<<sum<<std::endl;
}

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<char, std::__1::char_traits<char> >::operator<<(int)
 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值