std :: function к функции-члену с переменным числом аргументов, а затем привяжите аргументы шаблона с переменным числом аргументов

У меня есть две функции-члены класса с переменным числом аргументов. Когда вызывается первый Init(...), я хочу создать std :: function для второй функции-члена класса, а затем привязать аргументы Init(...) к указателю функции.

Так что позже я могу просто вызвать mf_() без необходимости снова передавать все аргументы в Reset(...)

Я бы не хотел делать его шаблонным классом и хранить аргументы в кортеже.

Я пытаюсь заставить работать следующий пример:

#include <iostream>
#include <string>
#include <functional>

using namespace std;

class Foo
{
public:
    template<typename... T>
    void Init(T&... args)
    {
        cout << __func__ << endl;
        Print(args...);

        // bind args.. to Reset ..
        mf_ = std::bind(&Reset, args...);
       // mf_ = std::bind(&Foo::Reset, this, args...); ???
    }

    template<typename... T>
    void Reset(T&... args)
    {
        cout << __func__ << endl;
    }

    // std::function to Reset(...)
    std::function<void()> mf_;

private:
    template<typename First>
    void Print(First& arg)
    {
        cout << arg << endl;
    }

    template<typename First, typename... Rest>
    void Print(First& arg, Rest&... args)
    {
        cout << arg << " ";
        Print(args...);
    }
};

int main() 
{
    int arg1 = 1;
    int arg2 = 2;
    string arg3 { "test" };
    double arg4 = 1.10;

    Foo foo;
    foo.Init(arg1, arg2, arg3, arg4);

    //foo.mf_();
    return 0;
}

Ссылка на живой пример: http://cpp.sh/4ylm

Когда я компилирую, я получаю сообщение об ошибке

ошибка вывода / замены аргумента шаблона: 17:37:
примечание: не удалось вывести параметр шаблона '_Result'


person Ody    schedule 27.07.2016    source источник
comment
Пожалуйста, не редактируйте решения своих вопросов.   -  person Barry    schedule 27.07.2016


Ответы (1)


Проблема в том, что &Reset не является допустимым выражением указателя на член.

Вам нужно сказать &Foo::Reset, чтобы сформировать функцию указателя на член, и вам также необходимо указать указатель this, так что вы почти правы с:

   // mf_ = std::bind(&Foo::Reset, this, args...); ???

Но это все еще недействительно, потому что Reset - это шаблон функции, и поэтому вам нужно указать, какую специализацию шаблона вы имеете в виду.

Вы можете указать компилятору, какую специализацию вы хотите, предоставив явный список аргументов шаблона:

mf_ = std::bind(&Foo::Reset<T&...>, this, args...);

Или создав переменную правильного типа, инициализированную из &Foo::Reset, что позволяет компилятору определить, какую специализацию вы имеете в виду:

void (Foo::*f)(T&...) = &Foo::Reset;
mf_ = std::bind(f, this, args...);

Или создав определение типа для правильного типа и приведя &Foo::Reset к этому типу:

   using pmf_type = void (Foo::*)(T&...);
   mf_ = std::bind((pmf_type)&Foo::Reset, this, args...);
person Jonathan Wakely    schedule 27.07.2016
comment
Спасибо! Это работает. Обновил мой исходный вопрос с помощью демонстрации решения в реальном времени - person Ody; 27.07.2016