С++ определяет функции форматирования времени в терминах strftime
, для чего требуется запись struct tm
"break down time". Однако языки C и С++ 03 не обеспечивают потокобезопасный способ получения такой записи; для всей программы есть только один мастер struct tm
.
В С++ 03 это было более или менее нормально, потому что язык не поддерживал многопоточность; он просто поддерживал платформы, поддерживающие многопоточность, которые затем предоставляли такие объекты, как POSIX localtime_r
.
С++ 11 также определяет новые утилиты времени, которые взаимодействуют с типом non-broken-down time_t
, который будет использоваться для повторной инициализации глобального struct tm
. Но получение time_t
не является проблемой.
Мне что-то не хватает или эта задача все еще требует опоры на POSIX?
РЕДАКТИРОВАТЬ: Ниже приведен код обходного кода. Он поддерживает совместимость с многопоточными средами, которые обеспечивают ::localtime_r
и однопоточные среды, которые обеспечивают только std::localtime
. Он может быть легко адаптирован для проверки других функций, таких как posix::localtime_r
или ::localtime_s
или что-то-вы.
namespace query {
char localtime_r( ... );
struct has_localtime_r
{ enum { value = sizeof localtime_r( std::declval< std::time_t * >(), std::declval< std::tm * >() )
== sizeof( std::tm * ) }; };
template< bool available > struct safest_localtime {
static std::tm *call( std::time_t const *t, std::tm *r )
{ return localtime_r( t, r ); }
};
template<> struct safest_localtime< false > {
static std::tm *call( std::time_t const *t, std::tm *r )
{ return std::localtime( t ); }
};
}
std::tm *localtime( std::time_t const *t, std::tm *r )
{ return query::safest_localtime< query::has_localtime_r::value >().call( t, r ); }