Früher habe ich ein Makro verwendet, um die Zeit zu messen, die ein Funktionsaufruf dauerte, wann immer ich das schnell überprüfen wollte. Jetzt, mit C++ 11 verfügbar, möchte ich endlich, dass hässliche Frieden Präprozessor Code entfernen und ersetzen sie durch etwas wie folgt aus:Perfekte Weiterleitung für ungültige und ungültige Funktionen
template <typename Functor, typename ... Args>
auto measure(Functor f, Args && ... args)
-> decltype(f(std::forward<Args>(args)...))
{
auto now = std::chrono::high_resolution_clock::now();
auto ret = f(std::forward<Args>(args)...);
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - now).count();
std::cout << "Time elapsed: " << elapsed << "ms" << std::endl;
return ret;
}
, die für Funktionen einwandfrei funktioniert, die etwas zurückgeben (das heißt nicht void
). So fühlte ich mich wie eine Überlastung für void
Funktionen benötigt - aber Sie können eine Funktion nicht nur auf Rückgabetyp überladen.
Ich habe versucht, dieses Problem mit einigen Vorlagen Magie zu umgehen, aber ohne Erfolg; noch der Compiler beschwert sich, dass die Funktion measure
zweimal definiert:
template <
typename Functor, typename ... Args,
typename ReturnType = typename std::enable_if<
!std::is_void<
typename std::result_of<Functor(Args...)>::type
>::value,
typename std::result_of<Functor(Args...)>::type
>::type
>
ReturnType measure(Functor f, Args && ... args)
{
auto now = std::chrono::high_resolution_clock::now();
auto ret = f(std::forward<Args>(args)...);
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - now).count();
std::cout << "Time elapsed: " << elapsed << "ms" << std::endl;
return ret;
}
template <
typename Functor, typename ... Args,
typename ReturnType = typename std::enable_if<
std::is_void<
typename std::result_of<Functor(Args...)>::type
>::value
>::type
>
ReturnType measure(Functor f, Args && ... args)
{
auto now = std::chrono::high_resolution_clock::now();
f(std::forward<Args>(args)...);
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - now).count();
std::cout << "Time elapsed: " << elapsed << "ms" << std::endl;
}
Gibt es eine Möglichkeit, um dieses?
UPDATE
Hier ist die Funktion, die ich jetzt bin mit dank R. Martinho Fernandes:
template <typename Functor, typename ... Args>
auto measure(Functor f, Args && ... args)
-> decltype(f(std::forward<Args>(args)...))
{
struct scoped_timer
{
scoped_timer() : now_(std::chrono::high_resolution_clock::now()) {}
~scoped_timer()
{
auto elapsed = std::chrono::duration_cast<
std::chrono::milliseconds
>(std::chrono::high_resolution_clock::now() - now_).count();
std::cout << "Time elapsed: " << elapsed << "ms" << std::endl;
}
private:
std::chrono::high_resolution_clock::time_point const now_;
} scoped_timer;
return f(std::forward<Args>(args)...);
}
Siehe http://flamingdangerzone.com/cxx11/2012/06/01/almost-static-if.html#evolution –
Elegant [Idee] (http://stackoverflow.com/a/17748197/1137388) (von [R. Martinho Fernandes] (http://stackoverflow.com/users/46642/r-martinho- fernandes)). Die einzige Änderung, die ich machen würde, würde '' scoped_timer() 's Code in einen' try-catch'-Block setzen, der jede ausgelöste Ausnahme verschluckt. Semantisch glaube ich, dass es sinnvoll ist, nicht die Zeit anzugeben, die "f" benötigt, um ausgeführt zu werden, wenn sie nicht erfolgreich abgeschlossen wird. Leider ist dies nicht so offensichtlich in Bezug auf mögliche Ausnahmen, die von "<<" ausgelöst werden. Wäre ein alter 'printf' eine bessere Alternative (bezüglich der Ausnahmesicherheit)? Ich weiß es nicht. –