Ich brauchte einen Weg, wie die Ausführungszeit einer Funktion zu messen. Ich fand diese sehr gute Antwort auf SO https://stackoverflow.com/a/21995693/3179492. Es ist eine perfekte Lösung.Warum kann der Compiler nicht um die ungültige Verwendung der nicht statischen Elementfunktion herum arbeiten
Es verwendet einen Funktionszeiger mit variadischen Parameterliste. Hier
ist die 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));
}
Dieser Code kompiliert nicht, weil foo_member
nicht statisch ist. Die Fehlermeldung lautet invalid use of non-static member function
.
Es gibt einige Möglichkeiten, wie Sie das Problem lösen können. Für mich ist die eleganteste, kürzeste und effektivste Weg ist dies:
printf("execution time=%ld\n", measure::execution([&foo, &x]() { foo.foo_member(x); }));
Das heißt, ich habe eine Lambda-Funktion verwenden, um die Linie zusammengestellt zu bekommen.
Ich frage mich nur, warum der Compiler konnte es nicht für mich tun? Der Code Pfad ist genau definiert, wie die erste Version in eine Lambda-Funktion mit dem Capture-Mechanismus zu übersetzen. Wenn Sie erkennen, was ein moderner C++ Compiler mit dem Code zu tun wäre dies in der Tat sein, eine des einfachstenen Code Neuordnungs ...
Hinweis:
Es ist mit diesen gcc
Fahnen zusammengestellt: -Wall -Werror -Wextra -std=c++11
Warum würden Sie der Compiler erwarten, dass dies für Sie automatisch zu generieren? Eine andere Möglichkeit, dies zu erreichen, ist die Verwendung von 'std :: bind()'. –
Einige Fragen, die sofort gestellt würden, wenn das erlaubt wäre: Was wäre der Typ von 'foo.foo_member'? Wäre es ein Compiler-generierter Typ? Würde das bedeuten, dass "foo.foo_member == foo.foo_member" scheitern würde und sich beschweren würde, dass der Vergleich zwei nicht verwandte Typen betrifft? Wenn ja warum? Wäre es nicht sinnvoll, 'auto x = y 'zuzulassen? foo.a: bar.a; '? Wie könnte das Feature neu gestaltet werden, um dies zu unterstützen? ... Und zurück zum Zeichenbrett. Dies ist wahrscheinlich nicht die Antwort, aber es ist nicht so einfach, wie Sie es vorschlagen. – hvd
@ πάνταῥεῖ 'std :: bind()' benötigt eine andere Include-Datei. Die Lösung mit "Lambda" verwendet nur C++ - Code. Dies bedeutet für mich, dass der C++ - Compiler es ohne zusätzliche Informationen neu anordnen kann [in diesem Fall einschließlich der Überschrift 'functional'] –