2012-01-05 10 views
5

C++ 11 ha due nuovi tipi di dati di carattere integrale, char16_t e char32_t. Mi piacerebbe emularli per i compilatori che non hanno un tipo distinto per sovraccaricare le operazioni di I/O per vederli un carattere invece del loro valore intero.Completamente emulando tipi distinti di componenti distinti (in particolare: char16_t e char32_t)

Questi sono i requisiti:

  • distinti (senza typedef).
  • esatta larghezza su sistemi normali (ala uint16_t e uint32_t)
  • altre C++ 11 caratteristiche sono consentiti (vedi sotto primo tentativo)
  • deve giocare bello con letterali; char16_t c16 = u"blabla unicode text blabla"; deve funzionare.
  • se char16_t può essere utilizzato negli operatori matematici, ovviamente anche questo deve funzionare.

Il mio primo tentativo che fallisce nel reparto letterale era un enum fortemente tipizzato:

enum char16_t : uint16_t; 

Questo ha altri svantaggi pure, che potrebbe forse essere risolto fornendo agli operatori necessari me stesso (che è davvero per me andava bene).

+0

Non è chiaro il motivo per cui si sta tentando questo o quali strumenti si desidera vengano utilizzati. Il "primo tentativo" utilizza C++ 11. Non c'è modo di ottenere i letterali Unicode da un compilatore senza supporto Unicode garantito e nessun modo per manipolare le stringhe in fase di compilazione senza un compilatore C++ 11 recente. – Potatoswatter

risposta

1

Non credo che l'inizializzazione funzionerà perché non c'è molto spazio per farlo funzionare. Il problema è che l'inizializzazione si sta utilizzando nel tuo esempio non dovrebbe lavoro: la stringa letterale u"..." produce un un array di oggetti char16_t const e si desidera inizializzare un puntatore con esso:

char16_t const* c16 = u"..."; 

Inoltre, senza l'implementazione di char16_t nel compilatore è molto improbabile che supporti i valori letterali stringa char16_t. Il meglio che puoi ottenere è giocare a trucchi macro che sono destinati a fare la cosa giusta. Per ora, useresti per es. caratteri letterali ampi e quando si ottiene un compilatore che supporta char16_t, basta cambiare la macro per utilizzare i valori letterali char16_t. Anche a questo scopo, potrebbe essere necessario utilizzare un tipo di record che è più grande di 16 bit poiché wchar_t utilizza 32 bit su alcune piattaforme.

#define CONCAT(a,b) a##b 

#if defined(HAS_C16) 
# define C16S(s) CONCAT(u,s) 
#else 
# define C16S(s) reinterpret_cast<char16_t const*>(CONCAT(L,s)); 
struct char16_t 
{ 
    unsigned short value; 
}; 
#endif 


int main() 
{ 
    char16_t const* c16 = C16S("..."); 
} 

Ovviamente, è comunque necessario fornire tutti i tipi di operatori, ad es. per far funzionare l'intero aritmetico e le conversioni adatte.