调用包含可调用对象和参数的元组
Invoking a tuple containing both the invocable and the arguments
我正在尝试调用元组中的第一个参数并将第二个参数作为参数,但不知道该怎么做。
示例:
#include <tuple>
#include <functional>
struct S {
void operator()(int) {}
};
int main() {
S s;
auto t = std::make_tuple(s, 3);
std::invoke(s, 3);
// std::apply(std::invoke, t); // This is what I want to do
// std::apply(std::invoke<S, int>, t); // I would settle for this "Good Enough"
}
但是上面的代码无法编译,而且这个错误对我来说毫无帮助:
error: no matching function for call to '__invoke(void (&)(S&&, int&&), std::__tuple_element_t<0, std::tuple<S, int> >&, std::__tuple_element_t<1, std::tuple<S, int> >&)'
(这是“足够好”的尝试)
任何人都知道如何做到这一点,或者如果不能做到这一点?
在 lambda 中包装 overload/template 函数解决了很多问题:
std::apply([](auto&&... args){ std::invoke(args...); }, t);
可能有转发:
std::invoke(std::forward<decltype(args)>(args)...);
否则因为std::invoke
是一个模板函数(采用转发引用),你需要更正类型:
std::apply(std::invoke<S&, int&>, t);
std::apply(std::invoke<S, int>, std::move(t));
关于错误阅读:std::__tuple_element_t<0, std::tuple<S, int> >&
是S&
,所以错误简化为
error: no matching function for call to __invoke(void (&)(S&&, int&&), S&, int&)
"
您需要 void (&)(S&, int&)
(或传递 S&&
、int&&
作为函数的参数)
std::apply
是一个选项,但您需要使用 lambda 适当地调用 f
:
std::apply([](auto f, auto... args) {
std::invoke(f, args...);
}, t);
之所以std::apply(std::invoke<S, int>, t)
不起作用,是因为std::invoke
被实例化为std::invoke(S&&, int&&)
。由于 t
是左值,它不能绑定到右值引用。
我正在尝试调用元组中的第一个参数并将第二个参数作为参数,但不知道该怎么做。
示例:
#include <tuple>
#include <functional>
struct S {
void operator()(int) {}
};
int main() {
S s;
auto t = std::make_tuple(s, 3);
std::invoke(s, 3);
// std::apply(std::invoke, t); // This is what I want to do
// std::apply(std::invoke<S, int>, t); // I would settle for this "Good Enough"
}
但是上面的代码无法编译,而且这个错误对我来说毫无帮助:
error: no matching function for call to '__invoke(void (&)(S&&, int&&), std::__tuple_element_t<0, std::tuple<S, int> >&, std::__tuple_element_t<1, std::tuple<S, int> >&)'
(这是“足够好”的尝试)
任何人都知道如何做到这一点,或者如果不能做到这一点?
在 lambda 中包装 overload/template 函数解决了很多问题:
std::apply([](auto&&... args){ std::invoke(args...); }, t);
可能有转发:
std::invoke(std::forward<decltype(args)>(args)...);
否则因为std::invoke
是一个模板函数(采用转发引用),你需要更正类型:
std::apply(std::invoke<S&, int&>, t);
std::apply(std::invoke<S, int>, std::move(t));
关于错误阅读:std::__tuple_element_t<0, std::tuple<S, int> >&
是S&
,所以错误简化为
error: no matching function for call to
__invoke(void (&)(S&&, int&&), S&, int&)
"
您需要 void (&)(S&, int&)
(或传递 S&&
、int&&
作为函数的参数)
std::apply
是一个选项,但您需要使用 lambda 适当地调用 f
:
std::apply([](auto f, auto... args) {
std::invoke(f, args...);
}, t);
之所以std::apply(std::invoke<S, int>, t)
不起作用,是因为std::invoke
被实例化为std::invoke(S&&, int&&)
。由于 t
是左值,它不能绑定到右值引用。