Я читал посты / статьи о лямбдах, указателях функций, анонимных функциях в целом и других связанных с этим вещах, но ничего из того, что я видел (я думаю), не достигло именно того, что я хочу сделать.
Кажется, что выполнить это должно быть довольно просто, но, скажем, у меня есть функция, содержащая вещи, которые я всегда хочу делать при вызове, но каждый раз, когда я вызываю ее, я хочу, чтобы она запускала функцию, которую я описываю (и должна использовать только один раз) в аргумент (эта анонимная функция является единственным аргументом).
Предполагая, что эта функция, которая принимает мою анонимную функцию в качестве аргумента, находится в main.cpp, поэтому она вызывается из main, возможно ли реализовать это простым способом?
В основном я пытаюсь выяснить синтаксис в C ++ для перехода от этого:
// Some function with partially duplicated code
void OriginalA()
{
DoThingsA();
// unique code
DoThingsB();
}
// Another function with partially duplicated code
void OriginalB()
{
DoThingsA();
// unique code
DoThingsB();
}
К этому:
// Encapsulate shared functionality
// <param name="action">User defined action</param>
void UniqueWrapper(Action action)
{
DoThingsA();
action();
DoThingsB();
}
// New implmentation of A
void NewA()
{
UniqueWrapper(() =>
{
// unique code
});
}
// New implementation of B
void NewB()
{
UniqueWrapper(() =>
{
// unique code
});
}
Который я нашел как №1 здесь: http://www.wildbunny.co.uk/blog/2012/11/01/10-steps-to-becoming-a-better-programmer/
Но такая установка, где буквально все, что вам нужно сделать для вызова:
theFunctionName(() => { /*unique things to do*/ });
Если этот ^^ является допустимым синтаксисом вызова, то я просто не уверен, как выглядит параметр в определении theFunctionName, очевидно, что это не (действие Action), как в примере выше.
Есть несколько способов сделать это, но не все будут работать на всех платформах (например, потому что им потребуются функции C ++ 11 (лямбда-выражения).
Более классический подход будет выглядеть примерно так (без анонимной функции):
#include <iostream>
typedef void(*Action)();
void UniqueWrapper(Action action) {
std::cout << "Generic Code 1" << std::endl;
action();
std::cout << "Generic Code 2" << std::endl;
}
void CustomAction(void) {
std::cout << "Custom Code" << std::endl;
}
int main(int argc, char **argv) {
UniqueWrapper(&CustomAction);
return 0;
}
Конечно, вы можете использовать некоторые макро-махинации, чтобы сделать это более «динамичным».
Как только вы примете код C ++ 11 (который должен иметь лямбду, как объяснено), вы можете сделать что-то вроде этого:
#include <iostream>
typedef void(*Action)();
void UniqueWrapper(Action action) {
std::cout << "Generic Code 1" << std::endl;
action();
std::cout << "Generic Code 2" << std::endl;
}
int main(int argc, char **argv) {
UniqueWrapper([](){
std::cout << "Custom Code" << std::endl;
});
return 0;
}
Конечно, есть место для дополнительных изменений, например, вы можете использовать std::function
а не указатель на функцию.
Заменить Action
аргумент с:
template<typename Function>
void UniqueWrapper(Function action) {
DoThingsA();
action(); // call the passed in function
DoThingsB();
};
Назовите это так:
void NewA() {
UniqueWrapper([]() {});
// ^^^^^^^
// C++11 lambda syntax
}
Вместо лямбды вы также можете использовать указатели на функции, функции-члены (используя std::mem_fn
) или функторы. Каждый вид вызываемого объекта будет работать.