関数の実行時間を測定する方法が必要でした。私はSO https://stackoverflow.com/a/21995693/3179492でこの非常に良い答えを見つけました。これは完璧なソリューションです。非静的メンバー関数の無効な使用のためにコンパイラが回避できない理由
バリデーションパラメータリストを持つ関数ポインタを使用しています。ここで
はMCVEです:
#include <algorithm>
#include <chrono>
#include <stdio.h>
class Foo
{
public:
auto foo_member(int x) -> void { printf("in foo_member(%d);\n", x); }
};
class measure
{
public:
template<typename F, typename ...Args>
static typename std::chrono::microseconds::rep execution(F func, Args&&... args)
{
auto start = std::chrono::system_clock::now();
func(std::forward<Args>(args)...);
auto duration = std::chrono::duration_cast<std::chrono::microseconds>
(std::chrono::system_clock::now() - start);
return duration.count();
}
};
int main()
{
Foo foo;
int x = 1234;
// this line does not compile
printf("execution time=%ld\n", measure::execution(foo.foo_member, x));
}
foo_member
が静的ではないので、このコードはコンパイルされません。エラーメッセージはinvalid use of non-static member function
です。
問題を解決する方法はいくつかあります。私にとっては、最もエレガントな、最短かつ効果的な方法はこれです:
printf("execution time=%ld\n", measure::execution([&foo, &x]() { foo.foo_member(x); }));
このことは、私がコンパイル行を取得するためにラムダ関数を使用します。
なぜ私はコンパイラがそれをできないのだろうと思っていますか?コードパスは正確に定義されています最初のバージョンをキャプチャメカニズムを使用してラムダ関数に変換します。あなただけの現代的なC++コンパイラがコードでやっている、これは実際にを並べ替える最も簡単なコードの一つであるものを実現すると...
注:-Wall -Werror -Wextra -std=c++11
:
それは、これらのgcc
フラグでコンパイルされました
あなたは、コンパイラがあなたのためにこれを自動的に生成することを期待するのはなぜ?これを実現する別の方法は単に 'std :: bind()'を使うことです。 –
これが許されていればすぐに出てくるいくつかの疑問: 'foo.foo_member'の型は何でしょうか?それはコンパイラ生成の型ですか?これは、 'foo.foo_member == foo.foo_member'が失敗するということは、比較に2つの無関係な型が含まれていると不平を言いますか?もしそうなら、なぜですか? 'auto x = y 'を許可するのは意味がありませんか? foo.a:bar.a; '?どのように機能を再設計してそれをサポートすることができましたか? ...そして、絵画ボードに戻って。これはおそらく答えではありませんが、あなたが提案するほどシンプルではありません。 – hvd
@πάνταῥεῖ 'std :: bind()'は別のインクルードファイルを必要とします。 'lambda 'の解決法は、C++コードのみを使用します。これは私のために、C++コンパイラは追加の情報(この場合、ヘッダ 'functional'を含む)を使わずに再配置することができます。 –