[英]When is c++17 std::apply/invoke necessary for programming?
As long as c++ is object-oriented programming language, I'm not sure if std::apply
or std::invoke
are necessary utility, which converts:只要 c++ 是面向对象的编程语言,我不确定
std::apply
或std::invoke
是否是必要的实用程序,它转换:
Object.Function(Args...)
into:进入:
std::invoke(Object, Function, Args)
that looks like c-style function call.看起来像 c 风格的 function 电话。 So my question is, when is this kind of scenario a necessary/convenience for daily programming?
所以我的问题是,这种场景什么时候是日常编程的必要/便利? Or else, is there a case that using
apply
/ invoke
makes things simpler?或者,是否存在使用
apply
/ invoke
使事情变得更简单的情况?
Would you help to give a good example case?你能帮忙举一个很好的例子吗? Thanks a lot!
多谢!
std::invoke
enables all Callable objects to be invoked uniformly , which contains pointers to member functions and pointers to member variables that cannot be invoked with regular function call form like f(args...)
std::invoke
允许统一调用所有Callable对象,其中包含指向成员函数的指针和指向无法使用常规 function 调用形式如f(args...)
调用的成员变量的指针
struct S {
void f(int i);
int x;
};
int main() {
auto mem_vptr = &S::x;
auto mem_fptr = &S::f;
S s;
std::invoke(mem_vptr, s); // invoke like s.*mem_vptr;
std::invoke(mem_fptr, s, 0); // invoke like (s.*mem_fptr)(0);
}
One of the real use of std::apply
is tuple unpacking, potentially nested. std::apply
的真正用途之一是元组拆包,可能是嵌套的。 Here's tested example:这是经过测试的示例:
#include <iostream>
#include <string>
#include <tuple>
#include <sstream>
// adapted from here: https://stackoverflow.com/a/48458312
template <typename>
constexpr bool is_tuple_v = false;
template <typename ...T>
constexpr bool is_tuple_v<std::tuple<T...>> = true;
template<typename Tval, typename ... T>
void linearize_tuple(std::stringstream &outbuf, const Tval& arg, const T& ... rest) noexcept {
if constexpr (is_tuple_v<Tval>){
outbuf << "{ ";
std::apply([&outbuf](auto const&... packed_values) {
linearize_tuple(outbuf, packed_values ...);
}, arg
);
outbuf << " }";
}
else{
outbuf << arg;
}
if constexpr(sizeof...(rest) > 0){
outbuf << ' ';
linearize_tuple(outbuf, rest ...);
}
}
template<typename ... T>
std::string args_to_string(const T& ... args) noexcept {
std::stringstream outbuf{};
if constexpr(sizeof...(args) > 0){
linearize_tuple(outbuf, args ...);
}
return outbuf.str();
}
int main(){
std::cout << args_to_string(
"test", 1, "2", 3.0, '0', std::tuple
{
"examination", 10, "20", 30.0, '1', std::tuple
{
"we need to go deeper", 100, "200", 300, '2'
}
}
);
}
It will print:它将打印:
test 1 2 3 0 { examination 10 20 30 1 { we need to go deeper 100 200 300 2 } }
and if you look at implementation of std::apply
, it's probably using std::invoke
like in example from cppreference .如果您查看
std::apply
的实现,它可能正在使用std::invoke
,就像cppreference 中的示例一样。 Key part:关键部分:
namespace detail {
template <class F, class Tuple, std::size_t... I>
constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>)
{
// This implementation is valid since C++20 (via P1065R2)
// In C++17, a constexpr counterpart of std::invoke is actually needed here
return std::invoke(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.