Если вы хотите просто указатель на указатель одной функции к одному экземпляру функции шаблона, который можно назвать точно с этими аргументами:
void(*pFunc)(WHAT_TO_TYPE_HERE?) = &Factory::testFunc;
pFunc(10, false, 'a', 11.5);
затем WHAT_TO_TYPE_HERE
становится
void(*pFunc)(int&&, bool&&, char&&, double&&) = &Factory::testFunc;
pFunc(10, false, 'a', 11.5);
Теперь недостатком является то, что мы зафиксировали статус rvalue/lvalue каждого аргумента в указателе функции, что раздражает.
Так этот помощник полезно:
template<class Sig, class Function>
struct testfunc_as_function_ptr;
template<class R, class...Args>
struct testfunc_as_function_ptr {
R(*)(Args...) operator()() const {
return [](Args...args){ return Factory::testFunc(std::forward<Args>(args)...); };
}
};
который довольно тупые, но дает вам:
void(*pFunc)(int,bool,char,double) = testfunc_as_function_ptr<void(int, bool, char, double)>{}();
, где вы можете выбрать подпись, и если подпись совместим с вызовом testFunc
оно работает.
Однако, если вы хотите указатель на ВСЕЙ шаблонной функции, а не только его экземпляр:
Это проблема ни капли диспетчерская.
Первое, что нужно понять, это то, что шаблоны не являются «вещами» на C++. шаблоны сделать вещи. Класс template делает классы - функция-шаблон выполняет функции.
Функциональный шаблон не является функцией. Это шаблон для создания функций.
Таким образом, ваш template<class...Args> void testFunc(Args&& ...args)
не является функцией. Это инструкции о том, как создать функцию - на самом деле, инструкции, как создавать любое количество различных функций. Эти функции являются «перегрузками» друг друга.
Для функций, когда вы их вызываете, перегрузка автоматически генерируется из аргументов, а затем выполняется перегрузка разрешения (возможно, исключая генерируемую перегрузку из рассмотрения, если, например, есть не-шаблонная функция, которая соответствует точно так же Что ж).
Указатель является (главным образом) конструкцией выполнения, а указатель на функцию должен указывать на фактическую «вещь» (фактическую функцию). Он не может указывать на шаблон.
Теперь, void testFunc(...)
является фактической функцией. Эта же функция создается и запускается независимо от того, какие аргументы переданы ей.Таким образом, вы можете иметь указатель на void testFunc(...)
.
Так что, хотя мы не можем иметь указатель на шаблон, вы можете создать указатель на конструкцию (объект), которая может отправить шаблон. Это, однако, требует, чтобы отправка была определена в том месте, в котором была создана конструкция, и вызов этой конструкции может достигать только тех определенных экземпляров.
Это своего рода бесплатная отправка, которая перегружает вас, определяется аргументами, которые вы передаете функции.
C++ не поддерживает сохранение шаблона генерации кода в объекте. Вы можете сохранить его в типе (классе), но не в реальном объекте.
Мы можем часто исправить эту проблему, осознав, что для тела функции шаблона может вообще не понадобиться все, что касается Args...
. Например, возможно, тело функции шаблона нужно только узнать, как превратить данный Arg
в строку?
В этом случае мы можем создать интерфейс, который выглядит как:
struct printable { virtual std::string to_string() const = 0; ~printable(); };
using printer = void(*)(std::vector<std::unique_ptr<printable>>);
и printer
является указателем на функцию, которая принимает vector
из printable
указателей. Затем мы можем написать код, который принимает произвольный тип T
и делает его printable
.
Это требует знать, что о функции, которую мы пытаемся произвести, необходимо знать о Args...
.
Вы можете зайти так далеко, как указатель вашей функции быть указателем на итерируемый диапазон с типом, эквивалентным boost::any
, а затем определить, какие типы на самом деле нужны и выполнять интроспекцию. Это эквивалент типа эквивалент void (*)(...)
C-style variardic, где вызываемая функция должна выполнять все виды гимнастики, чтобы убедиться, что все работает вручную.
'testFunc' - это не функция, а шаблон функции. Поэтому указатель на функцию (член) не может указывать на 'testFunc'. – chris
@chris Но он работает для указателя на бесконфликтную функцию. – nikitablack
Если с (...) все работает, тогда в чем вопрос? – zoska