What is the equivalent of Python function decorators in C ++?

I am migrating the Python metrics library to C ++. One API provided by the Python library is a function decorator that makes it easy to write synchronization data by function. By changing the definition of a function as

@timed('timing.foo')
def foo():
    ...

foo_result = foo() essentially turns into

start = time.time()
foo_result = foo()
post_metric_to_endpoint('timing.foo', time.time() - start)

In Function hooking in C ++ , we find this answer , which wraps up instances and imposes the burden of calling the synchronization function on the caller, which means that we will not receive performance data through the code base (this is an annoying update in the first place and is easily forgotten later). Similarly, this answer to Timing in an elegant way in C ++ requires changing call sites. This other answerthis question provides a way to wrap arbitrary blocks of code, which theoretically means that we could print the entire element of the function that we want and embed it inside the area. This is the closest I have found to what I want, but rather ugly, quite intrusive, and I'm not sure about the impact of performance.

Since this is intended to be used as a library, we can change the source of the functions we want to use over time; in fact, this is preferable since I would like every call to this function to be synchronized. Most discussions focus on special profiling in development, while I'm trying to create a system that will always be active in a production environment.

+4
source share
2

++ , , "" , ++ 14 generic lambdas. :

#include <iostream>

template<class T>
auto decorator(T&& func)
{
    // we create a closure below
    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;
}

int f(int x)
{
    std::cout << x * x << '\n';
    return x * x;
}

auto decorated = decorator(f);
auto double_decorated = decorator(decorator(f));

int main()
{
    decorated(5);
    double_decorated(10);
}

Live on Coliru

, , ( ..), . , lambda- mumbo-jumbo std::forward ++ 14

#include <iostream>

template<class T>
auto decorator(T func)
{
    // we create a closure below
    auto new_function = [func](auto... args)
    {
        std::cout << "BEGIN decorating...\n"; 
        auto result = func(args...);   
        std::cout << "END decorating\n";
        return result;
    };
    return new_function;
}

int f(int x)
{
    std::cout << x * x << '\n';
    return x * x;
}

auto decorated = decorator(f);
auto double_decorated = decorator(decorator(f));

int main()
{
    decorated(5);
    double_decorated(10);
}
+8

++ -, . , , . :

class Timed
{
//...
}

void foo()
{
    Timed t_;

    //Do the rest of work
}
+2

Source: https://habr.com/ru/post/1659679/


All Articles