Шаблон функции-члена для вызова функции на элементе данных с произвольными аргументами - PullRequest
0 голосов
/ 19 февраля 2020

Я работаю над базой кода C ++ 11 и задаюсь вопросом, как я могу вызвать любую функцию для типа члена, передавая произвольные аргументы. Обратите внимание, что, поскольку я использую C ++ 11, я не могу использовать что-то вроде std::invoke.

Я начал создавать шаблон функции в классе Outer, но мой начальный try дает мне ошибку компиляции.

#include <iostream>
#include <utility>
#include <type_traits>

struct Inner {
  void bar(int x) {
    std::cout << "Called: x=" << x << std::endl;
  }
};

struct Outer {
  explicit Outer(Inner *i) : b{i} {}
  void foo(int) {}
  Inner* b;

  template <typename Func, typename ... Args>
  void CallInner(Func&& f, Args&& ... args) {
    b->f(std::forward<Args>(args)...);
  }
};


int main() {
  Inner inner{};
  Outer outer(&inner);
  outer.CallInner(&Inner::bar, 5);
}

Попробуйте сами

Опять же, я хотел бы сохранить сигнатуру функции CallInner без изменений от приведенный выше пример кода.

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Так как f является указателем на функцию-член, необходимо сначала разыменовать ее перед вызовом:

(b->*f)(std::forward<Args>(args)...);
1 голос
/ 19 февраля 2020

У вас нет большого выбора в отношении изменения подписи, потому что требуется как минимум один дополнительный шаблон.

Правильный синтаксис немного сложнее:

struct Outer {
  explicit Outer(Inner *i) : b{i} {}
  void foo(int) {}
  Inner* b;

    template <typename Ret, typename ...FuncArgs,  typename ... Args>
    void CallInner(Ret (Inner::*f)(FuncArgs...), Args&& ... args) {
        (b->*f)(std::forward<Args>(args)...);
  }
};

Первый параметр CallInner должен быть указателем метода, и в контексте шаблона он должен быть шаблонизирован не только набором параметров шаблона c variadi FuncArgs, но и его типом возврата Ret. Затем вам также понадобится второй набор параметров шаблона variadi c для ссылок на переадресацию передаваемых вами аргументов (которые могут не совпадать с FuncArgs, следовательно, необходим отдельный набор variadi c типы шаблонов).

...