Inspired by @R Sahu answer here,
I solved it using macro and variadic args,
one of the feature python decorators have is implicit decoration using @ syntax as opposed to calling make_decorator function in every scope.
Using macro adds the extra syntactic sugar, my attempt:
#define DECORATOR(Class, ReturnType, function, arguments, before, after) \
template <typename Base> \
class DecoratorCls##function {public: \
Base* self; \
DecoratorCls##function(Base* object): self(object) {;} \
template <typename ... Args> \
ReturnType operator()(Args... args) { \
before(args...); \
ReturnType ans = self -> Decorator##function(args...); \
ReturnType processed_ans = after(ans); \
return processed_ans; \
} \
}; \
DecoratorCls##function<Class> function = DecoratorCls##function<Class>(this); \
ReturnType Decorator##function arguments
Usage:
void before_decoration(int &a1, int &a2) {
std::cout << "Berfore decoration with: " << a1 << " " << a2 << std::endl;
// a1 += 2; // Args can be processed if required
}
int after_decoration(int ans) {
std::cout << "After decoration" << std::endl;
return ans;
}
class MyClass {
private:
int private_variable;
public:
MyClass(int pv): private_variable(pv) {
std::cout << "Counstructor" << std::endl;
}
DECORATOR(MyClass, int, method, (int a, int b), before_decoration, after_decoration) {
std::cout << "Decorated method: " << std::endl;
std::cout << "Class data member: " << private_variable << std::endl;
std::cout << "method args: " << a << " " << b << std::endl;
return private_variable + a + b;
}
};
int main(int argc, char *argv[]) {
MyClass object = MyClass(10);
std::cout << "Member function Call: " << std::endl << object.method(4, 25) << std::endl;
return 0;
}
can be modified for decorating static function.
Assumptions:
- Appropriate standard/version available for variadic args and inline initialization of class data member.
- Inner class automatically friend to outer class.
before
and after
functions are assumed to be static functions but code can be modified to member functions of example class as self -> before(args...)
I know some assumptions have overlapping scope, mentioned for additional clarity