是否可以在没有显式特化的情况下调用可变参数模板函数?

时间:2018-05-04 09:50:48

标签: c++ templates variadic-templates c++17

我试图编写一个函数来转发可变参数模板函数的参数,类似于std::invoke。这是代码:

#include <functional>

template<class... Args>
void f(Args&&... args) { }

template<template<class...> class F, class... Args>
void invoke(F<Args...> f, Args&&... args) {
    f(std::forward<decltype(args)>(args)...);
}

int main() {
    invoke(f, 1, 2, 3);
    std::invoke(f, 1, 2, 3);
}

但是,invokestd::invoke都无法编译。 g ++抱怨说它无法推导出模板参数template<class ...> class F。那么是否可以在没有显式模板专门化的情况下调用可变参数模板函数?

2 个答案:

答案 0 :(得分:5)

请注意,函数模板代表函数的系列。例如,当您将其传递给函数时,它需要解析为模板的某个特化。我理解您尝试使用自定义invoke的参数(将函数模板捕获为模板),但遗憾的是,这只适用于类模板,而不是函数模板。

你需要另一层次的间接。即,传递一个将参数转发给f

的仿函数或lambda
invoke([](auto&&... xs) { f(decltype(xs)(xs)...); }, 1, 2, 3);

不同之处在于,现在参数是一个非模板类,因此可以由invoke推断。

通过此更改,您需要更改功能以完全推断出第一个参数:

template<class F, class... Args>
void invoke(F&& f, Args&&... args) {
  f(forward<Args>(args)...);
}

答案 1 :(得分:2)

如果函数包含在模板类中,那么您应该能够将此模板类作为模板模板参数传递:

#include <functional>

template<class... Args> struct Wrap
{
    static void f(Args&&... args) { }
};

template<template<class...> class F, class... Args>
void invoke(Args&&... args) {
    Wrap<Args...>::f(std::forward<Args>(args)...);
}

int main() {
    invoke<Wrap>(1, 2, 3);
}

online compiler