Пересылка аргументов в функцию члена шаблона

пример ideone


Мне нужно переслать некоторые предопределенные аргументы плюс некоторые переданные пользователем аргументы функции-члена.

#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.

пример ideone

Ответ 1

Я скомпилировал ваш код в gcc 4.9, предоставив аргументы шаблона указателю на функцию-член; как это

int main(){
// Compiles
forwarder(&example::f0, 10);
//Does not compile
forwarder(&example::f1, 10);
//Does compile, instantiate template with int or what ever you need
forwarder(&example::f1<int>,10)
}

Я считаю, что происходит то, что вам нужно создать экземпляр функции члена шаблона. это слишком сильно изменяет интерфейс? Я думаю, что любой ответ будет вращаться вокруг создания экземпляра этого шаблона-члена каким-то образом.