C ++中的Python函数修饰符等效于什么? [英] What's the equivalent of Python function decorators in C++?

查看:69
本文介绍了C ++中的Python函数修饰符等效于什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将Python指标库移植到C ++.Python库提供的一个API是函数装饰器,可轻松将定时数据记录在函数中.通过将函数定义修改为

I'm porting a Python metrics library to C++. One API the Python library provides is a function decorator to easily record timing data on functions. By modifying the function definition to be

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

foo_result = foo()本质上变成了

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


C ++中的函数挂钩中,我们找到了此答案定时在c ++中以一种优雅的方式要求更改调用站点.该问题的另一个答案提供了一种包装任意代码块的方法,从理论上讲,这意味着我们可以缩进整个代码段我们要计时的函数并将其嵌套在范围内.这是我找到的最接近我想要的东西,但是它很丑陋,相当令人讨厌,而且我不确定性能是否会受到影响.


In Function hooking in C++, we find this answer that wraps instances and places the burden of calling the timing function on the caller, which means we won't get performance data across the codebase (it's annoying to update in the first place, and easily forgotten later). Similarly, this answer to Timing in an elegant way in c++ requires altering the call sites. This other answer to that question provides a way of wrapping arbitrary blocks of code, which theoretically means we could indent the entire body of a function we want to time and nest it inside a scope. This is the closest I've found to what I want, but is pretty ugly, fairly intrusive, and I'm not sure of the performance impact.

由于它打算用作库,因此我们可以修改想要计时的函数的来源;实际上,这是更可取的,因为我希望对该函数的每次调用都计时.大多数讨论似乎都集中在开发中的临时概要分析上,而我正在尝试构建一个在生产环境中始终有效的系统.

Since this is meant to be used as a library, we can modify the source of the functions we want to time; in fact, this is preferable, as I'd like every call of that function to be timed. Most discussions seem to focus on ad-hoc profiling in development, whereas I'm trying to build a system that would be always active in a production environment.

推荐答案

尽管C ++对装饰器没有明确的语言支持,但事实证明,您可以使用C ++ 14通用lambda很好地模拟"它们.这是我的看法:

Although C++ does not have explicit language support for decorators, it turns out that you can "emulate" them quite nicely using C++14 generic lambdas. Here is my take on it:

#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);
}

在Coliru上直播

当然,您可以在装饰器内添加所需的任何内容(包括时序等),以上只是一个最小的示例.如果看起来太令人生畏,您可以忽略mumbo-jumbo std :: forward 和C ++ 14广义lambda捕获,而只需拥有

Of course inside the decorator you can add whatever you want (including timing etc), above is just a minimal example. If it looks too daunting you can ignore the mumbo-jumbo std::forward and C++14 generalized lambda captures and simply have

#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);
}

这篇关于C ++中的Python函数修饰符等效于什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆