Можно ли вызвать шаблонную функцию с переменным значением без явной специализации?
Я пытался написать функцию для пересылки аргументов для функции шаблона переменной, аналогично 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);
}
Тем не менее, оба мои invoke
а также std::invoke
не компилируется.
g++ жалуется, что не может вывести параметр шаблона template<class ...> class F
, Так возможно ли вызвать функцию шаблона с переменным числом аргументов без явной специализации шаблона?
2 ответа
Обратите внимание, что шаблон функции представляет собой семейство функций. Когда вы, скажем, передаете его в функцию, он должен разрешить определенную специализацию шаблона. Я понимаю, что вы пытаетесь сделать с параметром вашего кастома invoke
(захватите шаблон функции как шаблон), но, к сожалению, это будет работать только с шаблонами классов, но не шаблонами функций.
Вам нужен другой уровень косвенности. А именно, передавая функтор или лямбду, которая передает аргументы f
:
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)...);
}
Если функция обернута внутри класса шаблона, вы можете передать этот класс шаблона в качестве параметра шаблона шаблона:
#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);
}