То, что вы описали это хороший случай использования для указатель на функцию-член, что синтаксис выглядеть следующим образом:
// get the pointer to the function.
auto funPtr = &Obj::func1;
Obj obj;
// call the method using the function pointer
obj.(*funPtr)();
В вашем случае, вы можете получить указатель на функцию в качестве параметра и аргументы, пакет.
// F is the type of the function pointer.
// As arguments and return type of `f` can change, so it's type `F` can.
template<typename F, typename... Args>
void invokeAll(F f, Args... args) {
for (auto&& obj : retrieveObjs()) {
// We call member `f` with `obj`
// We expand the pack `args` to send it as multiple arguments
obj.(*f)(args...);
}
}
Вы сможете вызвать функцию таким же образом, что вы хотели:
// Notice the member function pointer syntax
invokeAll(&Obj::func1, 100);
// Work with multiple arguments, [100, "test"] will be packed into `args`
invokeAll(&Obj::func2, 100, "test");
В C++ 17, с std::invoke
, вы можете обобщить ваш случай еще дальше, позволяя любой тип функции, которая принимает в качестве параметра Obj
:
template<typename F, typename... Args>
void invokeAll(F f, Args... args) {
for (auto&& obj : retrieveObjs()) {
// invoke function `f` with `obj` as it's object and `args` as parameter.
std::invoke(f, obj, args...);
}
}
Если вы ш муравей, прямо сейчас, поддерживая больше вида функции, в том числе лямбды, вы можете использовать void_t
стиль SFINAE:
// The compiler will pick this function if `obj.(*f)(args...)` can compile
template<typename F, typename... Args>
auto invokeAll(F f, Args... args) -> void_t<decltype(std::declval<Obj>().(*f)(args...))> {
// Here's the constraint ------^
for (auto&& obj : retrieveObjs()) {
obj.(*f)(args...);
}
}
// The compiler will pick this function if `f(obj, args...)` can compile
template<typename F, typename... Args>
auto invokeAll(F f, Args... args) -> void_t<decltype(f(std::declval<Obj>(), args...))> {
// Here's the constraint ------^
for (auto&& obj : retrieveObjs()) {
f(obj, args...);
}
}
void_t
определяются следующим образом:
template<typename...>
using void_t = void;
Затем, что вы разблокировать этот синтаксис тоже:
invokeAll([](Obj& obj, int a){
// this block will be called for each `obj` in `retrieveObjs`
}, 100);
Если вы хотите поддерживать не-копируемые тип тоже ищут идеального экспедирование.
Да, это возможно. Попробуйте и вернитесь с проблемами, если столкнетесь с ними. Здесь у вас есть множество связанных вопросов. – Barry
Ну, есть ['std :: function'] (http://en.cppreference.com/w/cpp/utility/functional/function) и [' std :: bind'] (http: //en.cppreference. ком/ж/CPP/утилиты/функционал/привязки). Или ['std :: mem_fn'] (http://en.cppreference.com/w/cpp/utility/functional/mem_fn). Как и простые старые указатели на функции-члены. –
@JoachimPileborg Ваш комментарий - это ответ на самом деле, подумайте о его форматировании как ответе – alexeykuzmin0