libreria - C++ 11 alternativa a localtime_r
time h c++ ejemplos (1)
No te estás perdiendo nada.
El próximo estándar C (que probablemente saldrá este año) sí lo ha definido en el Anexo K:
struct tm *localtime_s(const time_t * restrict timer,
struct tm * restrict result);
¡Y esta nueva función es segura para hilos! Pero no te pongas muy feliz. Hay dos problemas principales:
localtime_s
es una extensión opcional a C11.C ++ 11 hace referencia a C99, no a C11.
local_time_s
no se encuentra en C ++ 11, opcional o no.
Actualizar
En los 4 años desde que contesté esta pregunta, también me he sentido frustrado por el pobre diseño de las herramientas de C ++ en esta área. Me motivó a crear herramientas modernas de C ++ para manejar esto:
http://howardhinnant.github.io/date/tz.html
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
auto local_time = make_zoned(current_zone(), std::chrono::system_clock::now());
std::cout << local_time << ''/n'';
}
Esto me acaba de dar salida:
2015-10-28 14: 17: 31.980135 EDT
local_time
es un emparejamiento de std::chrono::system_clock::time_point
y time_zone
indica la hora local.
Existen utilidades para dividir std::chrono::system_clock::time_point
en tipos de campo legibles por el ser humano, como año, mes, día, hora, minuto, segundo y subsegundos. Aquí hay una presentación que se enfoca en esas piezas (que no pertenecen a la zona horaria):
https://www.youtube.com/watch?v=tzyGjOm8AKo
Todo esto, por supuesto, es seguro para hilos (es C ++ moderno).
C ++ define las funciones de formateo de tiempo en términos de strftime
, lo que requiere un registro de "tiempo desglosado" de struct tm
. Sin embargo, los lenguajes C y C ++ 03 no proporcionan una forma segura de subprocesos para obtener dicho registro; solo hay una struct tm
maestra para todo el programa.
En C ++ 03, esto estuvo más o menos bien, porque el lenguaje no era compatible con multihilo; simplemente soportaba plataformas compatibles con multihilo, que luego proporcionaban instalaciones como POSIX localtime_r
.
C ++ 11 también define nuevas utilidades de tiempo, que interactúan con el tipo time_t
no descompuesto, que es lo que se usaría para reinicializar la struct tm
global struct tm
. Pero obtener un time_t
no es el problema.
¿Me estoy perdiendo algo o esta tarea aún requiere confianza en POSIX?
EDITAR: Aquí hay un código de solución. Mantiene la compatibilidad con entornos multiproceso que proporcionan ::localtime_r
y entornos de subproceso único que proporcionan solo std::localtime
. También se puede adaptar fácilmente para comprobar otras funciones, como posix::localtime_r
o ::localtime_s
o what-have-you.
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 ); }