2013-09-24 3 views
6

Sto utilizzando boost::lexical_cast<std::string>(double) per convertire i doppi in stringa, generando un flusso di byte serializzato JSON, ovvero (sul lato remoto) analizzato da .NET.Garanzia invariant locale di boost :: lexical_cast <>

Sono in grado di forzare .NET a utilizzare InvariantCulture per l'analisi, restituendo così risultati prevedibili su ogni lingua possibile.

Tuttavia, non sono riuscito a trovare questa garanzia nella documentazione boost::lexical_cast. Ho provato un po ', e funziona allo stesso modo per diversi set locali. Ma, non posso essere sicuro solo di alcuni test, mi manca qualcosa nella documentazione, o questo non può essere garantito a tutti, e devo usare qualcos'altro?

MODIFICA: Ho riscontrato un problema.

std::locale::global(std::locale("Czech")); 
std::cout << boost::lexical_cast<std::string>(0.15784465) << std::endl; 

rendimenti 0,15784465, e che è indesiderato. Posso forzare lo boost::lexical_cast<> a non conoscere le impostazioni locali?

risposta

5

Posso forzare il boost :: lexical_cast <> per non essere a conoscenza delle impostazioni locali?

No, non penso sia possibile. Il meglio che puoi fare è chiamare

std::locale::global(std::locale::classic()); 

per impostare il locale globale al locale "C" come boost::lexical_cast si basa sulla localizzazione globale. Tuttavia, il problema è che se da qualche altra parte nel codice la locale globale è impostata su qualcos'altro prima di chiamare boost::lexical_cast, allora hai ancora lo stesso problema. Pertanto, una soluzione robusta sarebbe imbue uno stringstream in questo modo, e si può sempre essere sicuri che questo funziona:

std::ostringstream oss; 
oss.imbue(std::locale::classic()); 
oss.precision(std::numeric_limits<double>::digits10); 
oss << 0.15784465; 
+4

Fondamentalmente, il problema è che le impostazioni locali di C++ non sono locali thread-locali e che rispettano RAII. – MSalters

1

Una soluzione migliore a questo problema è quello di utilizzare un boost::locale invece di uno std :: locale come la globale locale. Dal documentation:

Impostare la localizzazione globale ha effetti collaterali male ... colpisce ancora printf e librerie come boost :: lexical_cast dando la formattazione errata o inaspettata. In effetti, molte librerie di terze parti sono infranti in una situazione del genere. A differenza della libreria di localizzazione standard, Boost.Locale non modifica mai la formattazione del numero di base, anche quando utilizza back-end di localizzazione basati su std, quindi, per impostazione predefinita, i numeri vengono sempre formattati utilizzando le impostazioni internazionali in stile C. La formattazione numerica localizzata richiede flag specifici.

Boost locale richiede che si specifichi esplicitamente quando si desidera che la formattazione numerica sia in linea con le impostazioni locali, il che è più coerente con le decisioni di libreria recenti come std :: money_put.

+0

Come lo useresti con boost :: lexical_cast? – Managarm

+0

boost :: lexical_cast fa uso della locale globale. la libreria boost :: locale genera localizzazioni con un miglior comportamento di formattazione numerica (tra gli altri miglioramenti). Quindi, è sufficiente impostare la locale globale su una locale boost, e boost :: lexical_cast adotterà automaticamente il comportamento. Se non è chiaro fammelo sapere, farò un esempio. – Spacemoose

+0

Questo è sufficiente per me :) grazie! – Managarm