Python-like C++ decorators Python-like C++ decorators python python

Python-like C++ decorators


std::function provides most of the building blocks for my proposed solution.

Here is my proposed solution.

#include <iostream>#include <functional>//-------------------------------// BEGIN decorator implementation//-------------------------------template <class> struct Decorator;template <class R, class... Args>struct Decorator<R(Args ...)>{   Decorator(std::function<R(Args ...)> f) : f_(f) {}   R operator()(Args ... args)   {      std::cout << "Calling the decorated function.\n";      return f_(args...);   }   std::function<R(Args ...)> f_;};template<class R, class... Args>Decorator<R(Args...)> makeDecorator(R (*f)(Args ...)){   return Decorator<R(Args...)>(std::function<R(Args...)>(f));}//-------------------------------// END decorator implementation//-------------------------------//-------------------------------// Sample functions to decorate.//-------------------------------// Proposed solution doesn't work with default values.// int decorated1(int a, float b = 0)int decorated1(int a, float b){   std::cout << "a = " << a << ", b = " << b << std::endl;   return 0;}void decorated2(int a){   std::cout << "a = " << a << std::endl;}int main(){   auto method1 = makeDecorator(decorated1);   method1(10, 30.3);   auto method2 = makeDecorator(decorated2);   method2(10);}

Output:

Calling the decorated function.a = 10, b = 30.3Calling the decorated function.a = 10

PS

Decorator provides a place where you can add functionality beyond making the function call. If you want a simple pass through to std::function, you can use:

template<class R, class... Args >std::function<R(Args...)> makeDecorator(R (*f)(Args ...)){   return std::function<R(Args...)>(f);}


Here is my attempt. Works under C++14 (generic lambdas and return type deduction).

#include <iostream>#include <functional>/* Decorator function example,   returns negative (! operator) of given function*/template <typename T>auto reverse_func(T func){    auto r_func =    [=](auto ...args)    {         return !func(args...);     };    return r_func; }/* Decorator function example,   prints result of given function before it's returned*/template <typename T>auto print_result_func(T func){    auto r_func =     [=](auto ...args)    {        auto result = func(args...);        std::cout << "Result: " << result << std::endl;        return result;    };    return r_func;}/* Function to be decorated example,   checks whether two given arguments are equal*/bool cmp(int x, int y){    return x == y;}/* Decorator macro */#define DECORATE(function, decorator) \    decorator<decltype(function)>(function)int main(){    auto reversed = DECORATE(cmp, reverse_func);    auto print_normal = DECORATE(cmp, print_result_func);    auto print_reversed = DECORATE(reversed, print_result_func);    auto print_double_normal = DECORATE(print_normal, print_result_func);    auto print_double_reversed = DECORATE(print_reversed, print_result_func);    std::cout << cmp(1,2) << reversed(1,2) << std::endl;    print_double_normal(1,2);    print_reversed(1,2);    print_double_reversed(1,2);}


Here's a project on github that's pretty much a short tutorial on how to achieve this behavior for C++14 and up. It's a very flexible design and can decorate non-static functions as well. The author doesn't use anything complex either:

https://github.com/TheMaverickProgrammer/C-Python-like-Decorators