C++ define las funciones de formato de tiempo en términos de strftime
, que requiere un registro de "tiempo descompuesto" struct tm
. Sin embargo, los lenguajes C y C++ 03 no proporcionan una forma segura de subprocesos para obtener dicho registro; solo hay un maestro struct tm
para todo el programa.C++ 11 alternativa a localtime_r
En C++ 03, esto estuvo más o menos bien, porque el lenguaje no admitía el subprocesamiento múltiple; simplemente admitía plataformas compatibles con subprocesamiento múltiple, que luego proporcionaban instalaciones como POSIX localtime_r
.
C++ 11 define también nuevas utilidades de tiempo, que la interfaz con la no averiado time_t
tipo, que es lo que se usa para reinicializar el mundial struct tm
. Pero obtener un time_t
no es el problema.
¿Me está faltando algo o esta tarea todavía requiere dependencia de POSIX?
EDIT: Aquí hay un código de solución. Mantiene 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 verificar otras funciones, como posix::localtime_r
o ::localtime_s
o lo que quieras.
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); }
¿No puede simplemente envolver 'localtime' en una función que utiliza un mutex? ¿O alguna otra forma de cerradura más liviana? No veo cómo se requiere POSIX aquí. –
@Nicol: Sí, pero eso solo es seguro mientras nadie más intente hacer lo mismo. En otras palabras, funciona en un programa, no en una biblioteca. – Potatoswatter
Pero entonces estarían llamando a una función no segura para subprocesos de un código de subproceso, para que obtengan lo que se merecen. Simplemente podría exponer una función para que la usen, y si usan la C estándar en su lugar, entonces obtendrán un comportamiento indefinido. –