Мне нужно переслать некоторые предопределенные аргументы плюс некоторые переданные пользователем аргументы функции-члена.
#define FWD(xs) ::std::forward<decltype(xs)>(xs)
template<class T, class... Ts, class... TArgs>
void forwarder(void(T::*fptr)(Ts...), TArgs&&... xs)
{
T instance;
(instance.*fptr)(FWD(xs)..., 0);
// ^
// example predefined argument
}
forwarder(&example::f0, 10, 'a');
forwarder(&example::f1, 10, "hello", 5);
Это корректно работает для не-шаблонных функций-членов.
Указатель функции-члена, переданный в forwarder
, может также указывать на функции шаблона. К сожалению, компилятор не может вывести тип T
в этом случае:
struct example
{
void f0(int, int) { }
template<class T>
void f1(T&&, int) { }
};
// Compiles
forwarder(&example::f0, 10);
// Does not compile
forwarder(&example::f1, 10);
Ошибки:
prog.cpp:30:28: error: no matching function for call to 'forwarder(<unresolved overloaded function type>, int)'
forwarder(&example::f1, 10);
^
prog.cpp:20:6: note: candidate: template<class T, class ... Ts, class ... TArgs> void forwarder(void (T::*)(Ts ...), TArgs&& ...)
void forwarder(void(T::*fptr)(Ts...), TArgs&&... xs)
^
prog.cpp:20:6: note: template argument deduction/substitution failed:
prog.cpp:30:28: note: couldn't deduce template parameter 'T'
forwarder(&example::f1, 10);
Есть ли способ помочь компилятору вывести правильные типы без изменения интерфейса forwarder
?
Если нет, то какой лучший способ решить эту проблему без слишком сильного синтаксиса пользователя?
EDIT: Также было бы приемлемым передать указатель функции-члена в качестве параметра шаблона, возможно, через обертку. Целевая функция-член всегда будет известна во время компиляции. Псевдокод:
forwarder<WRAP<example::f0>>(10, 'a');
// Where WRAP can be a macro or a type alias.