调用包含可调用对象和参数的元组

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));

Demo

关于错误阅读: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 是左值,它不能绑定到右值引用。