2016-11-03 10 views
4

私はPythonのメトリックライブラリをC++に移植しています。 Pythonライブラリが提供する1つのAPIは、関数に関するタイミングデータを簡単に記録する関数デコレータです。 C++のPython関数デコレータに相当するものは何ですか?

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

foo_result = foo()

は、本質的に Function hooking in C++

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

になっている関数定義を変更することによりすることが、私たちは、インスタンスをラップして、発信者にタイミング関数を呼び出すの負担を課すthis answerを見つけますこれは、コードベース全体でパフォーマンスデータを取得しないことを意味します(最初は更新するのが煩わしく、後で簡単に忘れてしまいます)。同様に、this answerTiming in an elegant way in c++は、コールサイトを変更する必要があります。 This other answerは、任意のコードブロックをラップする方法を提供します。これは、理論的には、時間の対象となる関数の本体全体をインデントしてスコープ内にネストできることを意味します。これは私が欲しいと思っているものの中で最も近いものですが、かなり醜い、かなり侵入的なものです。パフォーマンスの影響についてはわかりません。

これはライブラリとして使用することを目的としているため、時間を計算する関数のソースを変更できます。実際には、私はすべての呼び出しが時間切れになるように、これが望ましいです。ほとんどの議論は開発のアドホック・プロファイリングに焦点を当てているのに対し、私は生産環境で常にアクティブなシステムを構築しようとしています。

+1

C++は、このPythonの機能に相当するものを持っていないことができ気力をくじく見える場合。 –

答えて

8

をC++は、デコレーターのための明示的な言語をサポートしていませんが、それはあなたがそれらを非常にうまくC++ 14件の一般的なラムダを使用して「エミュレート」できることが判明しました。あなたは(タイミングなどを含む)欲しいものは何でも追加することができますデコレータ内側もちろん

#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

以上、単なる最低限の例です。ここではそれが私の感想です。 それはあまりにもあなたがマンボ・ジャンボstd::forwardおよびC++ 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); 
} 
2

C++にはPythonのデコレータはありませんが、確定的な破壊があります。関数の時刻を設定するには、構築時にタイムスタンプを取得し、破壊時にレポートするクラスを作成します。次に、関数の最初の行としてインスタンスを宣言:

class Timed 
{ 
//... 
} 

void foo() 
{ 
    Timed t_; 

    //Do the rest of work 
} 
+0

これはわずかに異なるタイミングを生成します。パラメータのコピーに必要な時間と戻り値は含まれません(ただし、ほとんどの場合、タイミングコード自体が導入するオーバーヘッドに比べて無視できます)。 – Leon

関連する問題