GCC <5 是否有 std::p ut_time 的内置替代方案?

Is there a builtin alternative to std::put_time for GCC <5?

本文关键字:time 内置 方案 ut lt 是否 std GCC      更新时间:2023-10-16

我暂时停留在GCC4.8上。我想将当前时间打印为秒以外的其他时间。如果put_time有效,我的代码将很简单,如下所示:

std::cout << std::setw(24) << std::put_time(c_time, "[%T%z %F] ");

如果没有put_time,我将不得不手动访问c_time的元素并手动进行所有格式化,这将是a**的痛苦,如果可能的话,我宁愿避免。请注意,这并不意味着我永远不想以任何方式与 C 交互,即使是间接的 - 如果可能的话,我只想避免直接使用 C 进行编码。

但是,除了strftime之外,我找不到任何替代std::put_time,我想避免这样做,因为它需要几乎两倍的代码行,并且至少对我来说更难阅读。另外,这是C++,而不是 C,所以我想尽可能避开 C 函数。

我错过了什么吗?是否有在 GCC 4.8 下工作的std::put_time的内置替代方案?

请注意,它不必以完全相同的方式工作 - 如果它直接将其打印到输出,而不是流操纵器,那也很好,返回包含格式化时间的std::string的函数也是如此。

我已经做了很多谷歌搜索并找到了<chrono>,但这不起作用,因为它没有任何自动格式化时间的东西。我仍然需要手动完成,而且我很确定这会有更多的工作,因为我必须将自纪元以来的秒数解析为年、月、日等。

除了put_timechronoiomanip库中提供的时间输出之外,没有其他函数。

ctime库确实提供:strftimectimeasctime

由于 http://stackoverflow.com 不允许有关查找 3个第三方库的问题,我猜您只是在要求有人指导您使用strftimestd::put_time(c_time, "[%T%z %F] ")可以按以下格式编写:

char foo[24];
if(0 < strftime(foo, sizeof(foo), "[%T%z %F] ", c_time)) cout << foo << endl;

另外,这是C++,而不是 C,所以我想尽可能避开 C 函数。

这是一种非常愚蠢的心态。put_time在引擎盖下使用std::strftime

分机#10

返回:未指定类型的对象...其中函数f定义为:

template <class charT, class traits>
void f(basic_ios<charT, traits>& str, const struct tm* tmb, const charT* fmt) {
/* ... */
typedef time_put<charT, Iter> TimePut;
/* ... */
}

time_put的定义在locale.time.put.virtuals#1中:

效果:将参数t的内容格式化为放置在输出序列s上的字符。格式由 参数格式和修饰符,解释为格式相同 标准库函数的字符串参数中的说明符strftime()......

另一种解决方案是从后来的 GCC 标头中剥离std::put_time的定义,因为底层设施std::time_put仍然存在于 GCC 4.8 中,并且定义不是很复杂。这是从GCC 7.4的<iomanip>复制的,并为清楚起见进行了编辑:

#if __GNUC__ && __GNUC__ < 5
#include <ostream>  // std::basic_ostream
#include <ios>      // std::ios_base
#include <locale>   // std::use_facet, std::time_put
#include <iterator> // std::ostreambuf_iterator
template<typename CharT>
struct _put_time                   
{                                                                     
const std::tm* time;
const char *fmt;
};

template<typename CharT>
inline _put_time<CharT>
put_time(const std::tm* time, const CharT* fmt)
{ return { time, fmt }; }

template<typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits> &os, _put_time<CharT> f)
{   
typedef typename std::ostreambuf_iterator<CharT, Traits> Iter;
typedef std::time_put<CharT, Iter> TimePut;

const CharT* const fmt_end = f.fmt + Traits::length(f.fmt);
const TimePut& mp = std::use_facet<TimePut>(os.getloc());

std::ios_base::iostate err = std::ios_base::goodbit;
try {
if (mp.put(Iter(os.rdbuf()), os, os.fill(), f.time, f.fmt, fmt_end).failed())
err |= std::ios_base::badbit;
}
catch (...) {
err |= std::ios_base::badbit;
}  

if (err)
os.setstate(err);
return os;
} 
#endif