указатель на функцию-член в выражении fold

Этот код вызывает & foo :: next несколько раз

struct foo
{
    foo& next()
    {
        return *this;
    }
};

template<typename Obj>
void tmp_funct_1(Obj& obj)
{}

template<typename Obj, typename Func, typename... Other>
void tmp_funct_1(Obj& obj, Func func, Other... other)
{
    tmp_funct_1((obj.*func)(), other...);
}

теперь я хочу заменить рекурсивные вызовы одним выражением

Пример:

template<typename Obj, typename... Func>
void tmp_funct_2(Obj& obj, Func... func)
{
    (obj .* ... .* func());
}

Он не компилируется, потому что правильный синтаксис для указателя на вызов участника

(obj.*func)()

Как я могу достичь того же результата, используя выражение сложения шаблона? Спасибо!

int main()
{
    foo obj;
    auto to_foo = &foo::next;

    tmp_funct_1(obj, to_foo, to_foo, to_foo);
//  tmp_funct_2(obj, to_foo, to_foo, to_foo);
}

Ответ 1

Следующий код работает для одного аргумента, но не для нескольких:

template<typename Obj, typename... Func>
void tmp_funct_2(Obj& obj, Func... func)
{
    (obj .* ... .* func)();
}

int main()
{
    foo obj;
    auto to_foo = &foo::next;
    tmp_funct_2(obj, to_foo);
}

Проблема в том, что выражение fold не расширяется до вложенного вызова указателей на функции...

(((((obj.*to_foo)().*to_foo)()).*to_foo)());

... но он скорее расширяется до чего-то вроде...

obj.*func0.*func1.*func2.*func3

... это не то, что вы хотите.


Если вы не перегрузите operator.*, Я думаю, вы застряли с рекурсивным подходом здесь. В противном случае вы можете использовать некоторое временное хранилище и сбрасывать запятую:

template<typename Obj, typename... Func>
void tmp_funct_2(Obj& obj, Func... func)
{
    auto* temp = &obj;
    ((temp = &((*temp).*func)()), ...);
}

живой пример на wandbox.org