Можно ли вызвать шаблонную функцию с переменным значением без явной специализации? - PullRequest
0 голосов
/ 04 мая 2018

Я пытался написать функцию для пересылки аргументов для функции шаблона переменной, аналогично 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 ]

0 голосов
/ 04 мая 2018

Обратите внимание, что шаблон функции представляет собой семейство функций. Когда вы, скажем, передаете его функции, которую необходимо разрешить для определенной специализации шаблона. Я понимаю, что вы пытаетесь сделать с параметром вашего пользовательского 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)...);
}
0 голосов
/ 04 мая 2018

Если функция обернута внутри класса шаблона, вы можете передать этот класс шаблона в качестве параметра шаблона:

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

онлайн-компилятор

...