对于 GCC <5,是否有 std::put_time 的内置替代方案?

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

我暂时停留在 GCC4.8 上。我想将当前时间打印为秒以外的时间。如果 put_time 有效,我的代码会很简单,像这样:

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

如果没有 put_time,我将不得不手动访问 c_time 的元素并手动进行所有格式设置,这将是一个痛苦的事情,而我如果可能的话,宁愿避免。请注意,这个 并不 意味着我从不想以任何方式与 C 交互,即使是间接交互——我只是想避免编码如果可能,直接在 C 中。

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

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

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

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

Also, this is C++, not C, so I'd like to steer clear of C functions whenever possible.

这是一种非常愚蠢的心态。 put_time 在后台使用 std::strftime

ext.manip#10

Returns: An object of unspecified type ... where the function f is defined as:

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:

Effects: Formats the contents of the parameter t into characters placed on the output sequence s. Formatting is controlled by the parameters format and modifier, interpreted identically as the format specifiers in the string argument to the standard library function strftime() ...

除了 put_time for the outputing of time provided in the chrono or the iomanip 库之外没有其他功能。

ctime 库提供:strftime, ctime, and asctime.

由于 http://whosebug.com 不允许有关查找 3rd 方图书馆的问题,我猜你只是在找人指导你使用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;

另一个解决方案是从后来的 GCC header 中剥离 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