Есть ли встроенная альтернатива 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 под капотом.

ext.manip # 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определение в 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
Другие вопросы по тегам