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的特性所致