Trước đây tôi đã sử dụng một macro để đo thời gian mà một cuộc gọi hàm đã thực hiện bất cứ khi nào tôi muốn kiểm tra nhanh. Bây giờ, với C++ 11 có sẵn, tôi muốn để cuối cùng loại bỏ rằng hòa bình xấu xí của mã tiền xử lý và thay thế bằng một cái gì đó như thế này:Chuyển tiếp hoàn hảo cho các chức năng trả về vô hiệu và không có hiệu lực
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;
}
nào hoạt động tốt cho các chức năng mà trở về một cái gì đó (ví dụ: không void
). Vì vậy, tôi cảm thấy như tôi cần một sự quá tải cho các chức năng void
- nhưng bạn không thể quá tải một chức năng chỉ trên kiểu trả về.
Tôi đã cố gắng giải quyết vấn đề này bằng cách sử dụng một số mẫu ma thuật, nhưng vô ích; trình biên dịch vẫn than phiền rằng hàm measure
được xác định hai lần:
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;
}
Có cách nào khác không?
CẬP NHẬT
Dưới đây là chức năng bây giờ tôi đang sử dụng nhờ vào 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)...);
}
Xem http://flamingdangerzone.com/cxx11/2012/06/01/almost-static-if.html#evolution –
Thanh lịch [ý tưởng] (http://stackoverflow.com/a/17748197/1137388) (bởi [R. Martinho Fernandes] (http://stackoverflow.com/users/46642/r-martinho-fernandes)). Thay đổi duy nhất tôi sẽ thực hiện sẽ đặt mã '~ scoped_timer()' trong một khối 'try-catch' mà nuốt bất kỳ ngoại lệ nào. Về mặt ngữ nghĩa, tôi tin rằng nó không có nghĩa là không báo cáo thời gian 'f' cần chạy nếu nó không hoàn thành thành công. Thật không may, điều này không quá rõ ràng về các ngoại lệ có thể được đưa ra bởi '<<'. Liệu một 'printf' cũ có thể là một lựa chọn tốt hơn (liên quan đến an toàn ngoại lệ)? Tôi không biết. –