Come altri hanno detto, non c'è davvero nessuna convenienza threadsafe e ora portatile formattazione approccio a qualsiasi standard C++ a disposizione, ma c'è qualche tecnica preprocessore arcaica ho trovato utilizzabili (grazie a Andrei Alexandrescu a CppCon 2015 slitta 17 & 18):
std::mutex gmtime_call_mutex;
template< size_t For_Separating_Instantiations >
std::tm const * utc_impl(std::chrono::system_clock::time_point const & tp)
{
thread_local static std::tm tm = {};
std::time_t const time = std::chrono::system_clock::to_time_t(tp);
{
std::unique_lock<std::mutex> ul(gmtime_call_mutex);
tm = *std::gmtime(&time);
}
return &tm;
}
#ifdef __COUNTER__
#define utc(arg) utc_impl<__COUNTER__>((arg))
#else
#define utc(arg) utc_impl<__LINE__>((arg))
#endif
Qui dichiariamo funzione con size_t
argomento di un template e il puntatore di tornare a membro statico std::tm
. Ora ogni chiamata di questa funzione con argomenti modello diversi crea una nuova funzione con la nuova variabile statica std::tm
. Se la macro __COUNTER__
è definita, dovrebbe essere sostituita dal valore intero incrementato ogni volta che viene utilizzata, altrimenti usiamo la macro __LINE__
e in questo caso meglio per essere sicuri di non chiamare la macro utc
due volte in una riga.
globale gmtime_call_mutex
proteggere non threadsafe std::gmtime
chiamata in ogni esemplificazione, e almeno in Linux non dovrebbe essere un problema di prestazioni, come l'acquisizione di blocco viene dapprima eseguita come correre spinlock, e nel nostro caso non dovrebbe mai finire con filo reale serratura.
thread_local
assicura che thread diversi che eseguono lo stesso codice con le chiamate utc
funzionino ancora con diverse variabili std::tm
.
Esempio di utilizzo:
void work_with_range(
std::chrono::system_clock::time_point from = {}
, std::chrono::system_clock::time_point to = {}
)
{
std::cout << "Will work with range from "
<< (from == decltype(from)()
? std::put_time(nullptr, "beginning")
: std::put_time(utc(from), "%Y-%m-%d %H:%M:%S")
)
<< " to "
<< (to == decltype(to)()
? std::put_time(nullptr, "end")
: std::put_time(utc(to), "%Y-%m-%d %H:%M:%S")
)
<< "."
<< std::endl;
// ...
}
fonte
2016-03-20 19:53:05
Wow, queste funzioni sono quasi altrettanto ben progettati come 'strtok'. – CodesInChaos
"La programmazione in C++ non dovrebbe essere facile" Suppongo che questa sia ancora la filosofia dominante - è necessario qualcosa che si scrive qualcosa a meno che non sia un minimo assoluto. – zzz777