对于 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
。
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 方图书馆的问题,我猜你只是在找人指导你使用strftime
? std::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
我暂时停留在 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
。
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 sequences
. Formatting is controlled by the parameters format and modifier, interpreted identically as the format specifiers in the string argument to the standard library functionstrftime()
...
除了 put_time
for the outputing of time provided in the chrono
or the iomanip
库之外没有其他功能。
ctime
库提供:strftime
, ctime
, and asctime
.
由于 http://whosebug.com 不允许有关查找 3rd 方图书馆的问题,我猜你只是在找人指导你使用strftime
? std::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