Есть ли встроенная альтернатива std::put_time для GCC <5?
Я застрял на GCC4.8 в настоящее время. Я хочу распечатать текущее время как что-то кроме секунд. Если put_time
работал, мой код был бы что-то простое, как это:
std::cout << std::setw(24) << std::put_time(c_time, "[%T%z %F] ");
Без put_time
Я должен был бы получить доступ к элементам c_time
вручную и делайте все форматирование вручную, что было бы неприятно в a** и является чем-то, чего я бы предпочел избежать, если это возможно. Обратите внимание, что это не означает, что я никогда не хочу взаимодействовать с C каким-либо образом, даже косвенно - я просто хотел бы, по возможности, избегать непосредственного программирования на C.
Тем не менее, я не могу найти альтернативы std::put_time
, Помимо strftime
, чего я бы хотел избежать, потому что он требует почти вдвое больше строк кода и намного труднее читать, по крайней мере, для меня. Кроме того, это C++, а не C, поэтому я хотел бы избежать функций C, когда это возможно.
Я что-то пропустил? Есть ли встроенная альтернатива std::put_time
который работает под GCC 4.8?
Обратите внимание, что он не должен работать точно так же - если он, скажем, печатает его непосредственно на выходе, а не является потоковым манипулятором, это тоже будет прекрасно, как и функция, которая возвращает std::string
содержащий отформатированное время.
Я сделал много Googling и нашел <chrono>
, но это не работает, потому что у него нет ничего для автоматического форматирования времени. Мне все еще придется делать это вручную, и я уверен, что это будет больше работы, так как мне придется анализировать количество секунд, начиная с эпохи, в год, месяц, день и т. Д.
2 ответа
Там нет никаких функций, кроме put_time
для вывода времени, указанного в chrono
или iomanip
библиотека.
ctime
библиотека обеспечивает: strftime
, ctime
, а также asctime
,
Поскольку http://stackru.com/ не разрешает вопросы о поиске сторонних библиотек, я собираюсь догадаться, что вы просто просите кого-нибудь, чтобы направить вас на использование 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;
Кроме того, это C++, а не C, поэтому я хотел бы избежать функций C, когда это возможно.
Это довольно глупое мышление. put_time
использования std::strftime
под капотом.
Возвращает: объект неопределенного типа... где функция
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
определение в http://eel.is/c++draft/locale.time.put.virtuals:
Эффекты: форматирует содержимое параметра
t
на символы, помещенные в выходную последовательностьs
, Форматирование контролируется параметрами формата и модификатора, идентично интерпретируемыми как спецификаторы формата в строковом аргументе стандартной библиотечной функции.strftime()
...
Другое решение - убрать определение std::put_time
из более позднего заголовка GCC, поскольку базовое средство 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