Compilazione per stringa e wstring

7

Sto creando una libreria. Voglio usarlo in più progetti che possono usare multi-byte o unicode ( std::string o std::wstring ). Ho adottato il vecchio metodo MS di compilazione condizionale:

namespace my_namespace {
#ifdef UNICODE
    typedef std::wstring String;
    typedef std::wstringstream StringStream;
    #define Str(s) L##s
#else
    typedef std::string String;
    typedef std::stringstream StringStream;
    #define Str(s) s
#endif
}

(La macro Str è per i letterali stringa. VC ++ contrassegna le stringhe ampie con L . Esempio: L"this is a wide string"; )

Ci sono modi migliori per farlo?

    
posta Johnny Mopp 22.07.2016 - 19:39
fonte

3 risposte

1

La vecchia tecnica Microsoft

La buona vecchia tecnica Microsoft ha servito milioni di applicazioni, quindi è definitivamente considerato un approccio valido e comprovato.

Tre osservazioni:

  • Microsoft utilizza questa compilazione condizionale non solo i pochi elementi fondamentali (TCHAR, TEXT, ...), ma anche per molte altre funzioni relative alle stringhe (vedere l'esempio nell'articolo MSDN) in modo che questo possa lavorare in modo coerente.

  • Devi stare attento alla combinazione di macro con namespace. Ad esempio Str() ha l'aspetto di una funzione normale, ma è una macro definita globalmente e non limitata al tuo spazio dei nomi (e da utilizzare senza prefisso dello spazio dei nomi). Ti suggerirei di usare maiuscole per rendere esplicito

  • Se inizi ora con una nuova base di codice, suggerirei di adottare la raccomandazione di Meyer di preferire l'alias di tipo su typedef.

Variante ridondante

Come in C ++ string / wstring , stringstream / wstringstream , ecc ... sono solo char / wchar_t specializzazioni di basic_string<X> / basic_stringstream<X> , definirei il tipi da utilizzare in base al tipo di carattere sottostante che si desidera:

namespace mine {
#ifdef UNICODE
    using Char = wchar_t; 
    #define Str(s) L##s
#else
    using Char = char; 
    #define Str(s) s
#endif
    using String = std::basic_string<Char>;
    using StringStream = std::basic_stringstream<Char>;
    // ...  a lot more but only once
}

Demo

Se necessario, potresti facilmente passare a char32_t se volessi lavorare con un Unicode a 32 bit su tutte le piattaforme (attualmente wchar_t su Windows è 16 bit e usa la codifica UTF16, mentre su linux è a 32 bit e UTF32) come si può usare u32string ).

Compilazione condizionale

In teoria si potrebbe immaginare una decisione runtime se eseguire unicode o meno. Ma per raggiungere questo obiettivo è necessario creare tutti gli oggetti utilizzando una fabbrica astratta . Questo sembra molto doloroso e complesso. Non parliamo del codice gonfiato con tutte le funzioni di stringa in doppio.

Un altro approccio potrebbe essere l'uso di alcuni modelli per definire i tipi in fase di compilazione utilizzando un modello intelligente. Ma alla fine avresti bisogno di fare affidamento su alcune macro, che potresti definire negli script di compilazione per automatizzare la creazione di tutte le versioni. Come alla fine ti fiderai di loro, perché non facilitare l'approccio e usarli per quello che dovrebbero fare!

    
risposta data 25.08.2016 - 01:55
fonte
1

Per quel che vale, std::wstring non fa nulla di ciò che ti aspetteresti (è UCS-2, non UTF-16, sono diversi, il primo non può esprimere caratteri al di fuori del piano multilingue di base , incluso Emoji come U+1F44E THUMBS DOWN SIGN

risposta data 25.07.2016 - 21:28
fonte
0

In teoria puoi semplicemente usare il tipo di dati TCHAR, usare la versione 't' di tutte le funzioni stringa e compilare con le definizioni appropriate e tutto funziona ....

.... ma nel mondo reale, ci si ritroverà con alcune chiamate API che sono disponibili solo nel formato sbagliato e che è necessario convertire stringhe tra codifiche e Se non si conosce la codifica della codepage degli mbcs stringa questo sarà problematico. (L'ipotesi di default è che è codificata nella codepage corrente del sistema operativo - ma questo è un presupposto pericoloso dovuto alle reti!)

Altre cose che vanno storte includono il codice che presuppone che le stringhe wchar abbiano lo stesso numero di caratteri delle stringhe di caratteri e che l'unica conversione sicura di Unicode a MCBS sia di specificare la codepage UTF8 - Caratteri Unicode che non esistono la codepage di destinazione viene convertita nei caratteri "predefiniti", il che è un ottimo modo per perdere i caratteri asiatici e arabi su un server statunitense.

Infine, ricorda che le lettere Unicode possono aver bisogno di più caratteri wchar per memorizzare una singola lettera,

    
risposta data 26.08.2016 - 22:05
fonte

Leggi altre domande sui tag