[英]Elegant time print in C++11
這就是我想在C ++ 11中做的事情:給定兩個時間點(例如計時類)作為std::chrono::steady_clock::now()
,優雅地打印它們的時差,例如:
1 day 4 hours 3 minutes 45 seconds
要么
32 minutes 54 seconds 345 milliseconds
請注意,我對使用put_time
不感興趣,因為我想從最重要的單位時間開始打印。 我知道,它只是打印差異的解決方案,但它並不漂亮:我正在尋找一個優雅的解決方案:)
干杯!
持續時間可以算術。
#include <chrono>
#include <iostream>
#include <thread>
int main(){
using namespace std::chrono;
using day_t = duration<long, std::ratio<3600 * 24>>;
auto start = system_clock::now();
std::this_thread::sleep_for(seconds(1));
auto end = system_clock::now();
auto dur = end - start;
auto d = duration_cast<day_t>(dur);
auto h = duration_cast<hours>(dur -= d);
auto m = duration_cast<minutes>(dur -= h);
auto s = duration_cast<seconds>(dur -= m);
auto ms = duration_cast<seconds>(dur -= s);
std::cout << d.count() << " days, "
<< h.count() << " hours, "
<< m.count() << " minutes, "
<< s.count() << " seconds, "
<< ms.count() << " milliseconds\n";
return 0;
}
輸出:
template<typename T>
void print_time_diff(std::ostream& out, T prior, T latter)
{
namespace sc = std::chrono;
auto diff = sc::duration_cast<sc::milliseconds>(latter - prior).count();
auto const msecs = diff % 1000;
diff /= 1000;
auto const secs = diff % 60;
diff /= 60;
auto const mins = diff % 60;
diff /= 60;
auto const hours = diff % 24;
diff /= 24;
auto const days = diff;
bool printed_earlier = false;
if (days >= 1) {
printed_earlier = true;
out << days << (1 != days ? " days" : " day") << ' ';
}
if (printed_earlier || hours >= 1) {
printed_earlier = true;
out << hours << (1 != hours ? " hours" : " hour") << ' ';
}
if (printed_earlier || mins >= 1) {
printed_earlier = true;
out << mins << (1 != mins ? " minutes" : " minute") << ' ';
}
if (printed_earlier || secs >= 1) {
printed_earlier = true;
out << secs << (1 != secs ? " seconds" : " second") << ' ';
}
if (printed_earlier || msecs >= 1) {
printed_earlier = true;
out << msecs << (1 != msecs ? " milliseconds" : " millisecond");
}
}
這是一個使用可變參數模板和遞歸的易於擴展的解決方案。 它定義了ostream& operator<<(ostream&, const duration&)
以方便使用。
#include <chrono>
#include <iostream>
#include <tuple>
using day_t = std::chrono::duration<long long, std::ratio<3600 * 24>>;
template<typename> struct duration_traits {};
#define DURATION_TRAITS(Duration, Singular, Plural) \
template<> struct duration_traits<Duration> { \
constexpr static const char* singular = Singular; \
constexpr static const char* plural = Plural; \
}
DURATION_TRAITS(std::chrono::milliseconds, "millisecond", "milliseconds");
DURATION_TRAITS(std::chrono::seconds, "second", "seconds");
DURATION_TRAITS(std::chrono::minutes, "minute", "minutes");
DURATION_TRAITS(std::chrono::hours, "hour", "hours");
DURATION_TRAITS(day_t, "day", "days");
using divisions = std::tuple<std::chrono::milliseconds,
std::chrono::seconds,
std::chrono::minutes,
std::chrono::hours,
day_t>;
namespace detail {
template<typename...> struct print_duration_impl_ {};
template<typename Head, typename... Tail>
struct print_duration_impl_<Head, Tail...> {
template <typename Duration>
static bool print(std::ostream& os, Duration& dur) {
const auto started_printing = print_duration_impl_<Tail...>::print(os, dur);
const auto n = std::chrono::duration_cast<Head>(dur);
const auto count = n.count();
if (count == 0) {
return started_printing;
}
if (started_printing) {
os << ' ';
}
using traits = duration_traits<Head>;
os << count << ' ' << (count == 1 ? traits::singular : traits::plural);
dur -= n;
return true;
}
};
template<>
struct print_duration_impl_<> {
template <typename Duration>
static bool print(std::ostream& os, Duration& dur) {
return false;
}
};
template<typename...> struct print_duration {};
template<typename... Args>
struct print_duration<std::tuple<Args...>> {
template<typename Duration>
static void print(std::ostream& os, Duration dur) {
print_duration_impl_<Args...>::print(os, dur);
}
};
}
template<typename Rep, typename Period>
std::ostream& operator<<(std::ostream& os, const std::chrono::duration<Rep, Period>& dur) {
detail::print_duration<divisions>::print(os, dur);
return os;
}
通過專門化duration_traits
並將類型插入分區中的正確位置來添加新的持續時間。 例如,添加10毫秒的jiffy類型將涉及:
using jiffy_t = std::chrono::duration<long long, std::centi>;
DURATION_TRAITS(jiffy_t, "jiffy", "jiffies");
using divisions = std::tuple<std::chrono::milliseconds,
jiffy_t,
std::chrono::seconds,
std::chrono::minutes,
std::chrono::hours,
day_t>;
三行代碼還不錯!
在ideone.com上的實例 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.