Раньше я использовал макрос, чтобы измерить время вызова функции, когда я захотел быстро проверить это. Теперь, с C++ 11 доступны, я хотел бы, наконец, удалить этот уродливый мир препроцессора кода и заменить его чем-то вроде этого:Превосходная пересылка для функций void и non-void
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;
}
, который работает отлично подходит для функций, которые возвращают что-то (т.е. не void
). Поэтому мне показалось, что мне нужна перегрузка для функций void
, но вы не можете перегружать функцию только по типу возврата.
Я попытался обойти эту проблему, используя магию шаблонов, но безрезультатно; компилятор все еще жалуется, что функция measure
определяется два раза:
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;
}
Есть ли способ обойти это?
UPDATE
Вот функция Я сейчас, используя благодаря Р. 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)...);
}
См. Http://flamingdangerzone.com/cxx11/2012/06/01/almost-static-if.html#evolution –
Элегантный [идея] (http://stackoverflow.com/a/17748197/1137388) ([R. Martinho Fernandes] (http://stackoverflow.com/users/46642/r-martinho-fernandes)). Единственное изменение, которое я сделал бы, - это разместить код '~ scoped_timer()' в блоке 'try-catch', который проглатывает любое вызванное исключение. Семантически, я считаю, что имеет смысл не сообщать о времени, которое 'f' берет для запуска, если оно не завершено успешно. К сожалению, это не так очевидно в отношении возможных исключений, вызванных '<<'. Может ли старая «printf» стать лучшей альтернативой (в отношении безопасности исключений)? Я не знаю. –