Допустим, вы хотите написать функцию, которая передает непрозрачный дескриптор функции неизвестного типа (скажем, имя структуры, содержащей функцию с согласованным именем) и передает аргументы этой функции.
В невариантном случае, рассматривая однопараметрические функции для простоты, есть два способа сделать это: вы можете позволить функции переадресации принять аргумент произвольного типа и попытаться вызвать функцию форварди с ним,и компилятор будет жаловаться во время расширения шаблона, если он окажется несовместимым;или вы можете использовать decltype и различные другие механизмы, чтобы выяснить, какой тип параметра ожидает функция forwardee, и явно требовать аргумент этого типа.Я не знаю, есть ли какая-либо принятая терминология для них, поэтому я буду называть их «сквозной» и «прямой».
Метод сквозной передачи напрямую обобщает функции с произвольным числомпараметров, но метод с открытым исходным кодом - нет.
#include <iostream>
template<typename T, typename Arg>
void pass_through_1(Arg arg)
{
T::f(arg);
}
template<typename T> struct arg_of_1;
template<typename Ret, typename Arg>
struct arg_of_1<Ret (Arg)>
{
typedef Arg type;
};
template<typename T>
void up_front_1(typename arg_of_1<decltype(T::f)>::type arg)
{
T::f(arg);
}
template<typename T, typename... Args>
void pass_through_var(Args... args)
{
T::f(args...);
}
template<typename T> struct args_of_var;
template<typename...> struct type_list;
template<typename Ret, typename... Args>
struct args_of_var<Ret (Args...)>
{
// typedef Args... type; // can't do this
typedef type_list<Args...> type;
};
// template<typename T>
// void up_front_var(typename args_of_var<decltype(T::f)>::type... args) // can't do this
// {
// T::f(args...);
// }
struct test
{
static void f(int x) { std::cout << x*9 << std::endl; }
};
int main(int, char**)
{
pass_through_1<test>(7);
up_front_1<test>(8);
pass_through_var<test>(9);
// up_front_var<test>(10);
return 0;
}
Проблема в том, что пакетам параметров не разрешается быть автономными, только в качестве аргументов шаблона, и если вы заключаете их в вмещающий шаблоннет возможности развернуть и распаковать их на месте, только путем сопоставления с шаблоном.
У «впереди» есть некоторые преимущества, такие как улучшение самодокументирования и лучшая поддержка вывода типов (up_front можетсам будет дешифрован).Есть ли способ заставить его работать в вариационном случае?(Конечно, вы можете использовать std :: tuple, но это довольно неудовлетворительно.)