Уважаемое сообщество Stackoverflow,
Я все еще немного свободен sh в c ++, и я чесал голову и еще не нашел решения своей проблемы. Я уже некоторое время искал и пробовал что-то, и я дошел до того, что задать вопрос было бы более полезно и поучительно.
Проблема:
Я бы хотел создать класс или функцию, которая обертывает / украшает данную функцию с параметрами или без них. Как старый добрый @wrapthis в python или c# и т. Д.
Ближайшая вещь, которую я нашел до сих пор (элегантная, короткая и простая в использовании), взята из этого ответа stackoverflow: Эквивалентный декоратор C ++
Часть «почесывая голову» пытается передать функцию-указатель. Ошибка, которую я получаю:
Error (active) E0300 указатель на связанную функцию может использоваться только для вызова функции
Что, очевидно, означает, что каким-то образом указатель таким образом не разрешен, поэтому какие у меня здесь варианты?
Рабочий пример в качестве ответа был бы отличным!
Пример того, чего я пытаюсь достичь, можно найти ниже :
Something.h
class Something
{
private:
public:
Something() {}
void v_func_with_nothing() { std::cout << "v_func_with_nothing" << "\n"; }
void v_func_with_void(void) { std::cout << "v_func_with_void" << "\n"; }
void v_func_with_one_arg(int x) { std::cout << "v_func_with_one_arg" << x << " " << "\n"; }
void v_func_with_args(int x, int y) { std::cout << "v_func_with_args" << x << " " << y << "\n"; }
int return_func_with_nothing() { return 1; }
int return_func_with_void(void) { return 3; }
int return_func_with_one_arg(int x) { return x; }
int return_func_with_args(int x, int y) { return x+y; }
};
Decorator.h [Снова источник: Эквивалентный декоратор C ++ ]
template<typename T>
auto decorator(T&& func)
{
auto new_function = [func = std::forward<T>(func)](auto&&... args)
{
std::cout << "BEGIN decorating...\n";
auto result = func(std::forward<decltype(args)>(args)...);
std::cout << "END decorating\n";
return result;
};
return new_function;
}
main. cpp
#include <iostream>
#include "Something.h"
#include "Decorator.h"
int main()
{
Something* something = new Something();
auto somedeco = decorator(&something->return_func_with_one_arg);//<-- error here in argument
//int value = somedeco(**enter an argument**);
//std::cout << value << "\n";
return 0;
}
Спасибо!
РЕДАКТИРОВАТЬ: РЕШЕНИЕ
Основываясь на добрых ответах, приведенных ниже, я подумал о том, чтобы отредактировать этот пост на примере. Решением проблемы было использование лямбда.
Decorator.h : я создал 2 декоратора (один для функций возврата, один для функций void):
template<typename T>
auto DECO_R(T&& func)
{
try
{
auto new_function = [func = std::forward<T>(func)](auto&&... args)
{
std::cout << "BEGIN RETURN decorating...\n";
auto result = func(std::forward<decltype(args)>(args)...);
std::cout << "END RETURN decorating\n";
return result;
};
return new_function;
}
catch (const std::exception& ex)
{
std::cout << ex.what() << "\n";
}
}
template<typename T>
auto DECO_V(T&& func)
{
try
{
auto new_function = [func = std::forward<T>(func)](auto&&... args)
{
std::cout << "BEGIN VOID decorating...\n";
func(std::forward<decltype(args)>(args)...);
std::cout << "END VOID decorating\n";
};
return new_function;
}
catch (const std::exception& ex)
{
std::cout << ex.what() << "\n";
}
}
Основной. cpp: 2 примера
int main()
{
Something* something = new Something();
auto somedeco = DECO_R(
[&](int x) {
return something->return_func_with_one_arg(x);
});
int value = somedeco(255);
std::cout << value << "\n";
auto some_v_deco = DECO_V(
[&](int x) {
return something->v_func_with_one_arg(x);
});
some_v_deco(2);
return 0;
}
Выход
НАЧАТЬ ВОЗВРАТ декорирование ... END RETURN украшение 255
НАЧАТЬ ОТКРЫТЬ ОТКРЫТЬ ... v_func_with_one_arg2 END VOID decorating
Надеюсь, это поможет другим.