Ho lavorato su un adattatore iteratore UTF-8. Con ciò intendo un adattatore che trasforma un iteratore in una sequenza char
o unsigned char
in un iteratore in una sequenza char32_t
. Il mio lavoro qui è stato ispirato da questo iteratore che ho trovato online .
Tuttavia, osservando lo standard quando stavo iniziando la mia implementazione, mi sono reso conto che non sembra possibile implementare tale adattatore pur rispettando i requisiti che C ++ pone sugli iteratori.
Ad esempio, potresti creare un iteratore UTF-8 che soddisfi i requisiti di InputIterator? Sì, ma solo fino a quando l'iteratore che ti viene dato è non stesso un InputIterator. Perché?
Perché InputIterator richiede la possibilità di dereferenziare lo stesso iteratore più di una volta. Puoi anche dereferenziare più copie di quell'iteratore, purché siano tutte uguali.
Ovviamente, il dereferenziamento di un adattatore iteratore UTF-8 richiede sia il dereferenziamento che potenzialmente incrementare l'iteratore di base. E se l'iteratore è un InputIterator, non è possibile ripristinare il valore originale dopo averlo incrementato. E il fatto che le copie debbano funzionare significa che non è possibile memorizzare localmente un char32_t
che rappresenta il valore precedentemente decodificato. Avresti potuto fare questo:
auto it = ...
auto it2 = it; //Copies an empty 'char32_t'.
*it; //Accesses base iterator, storing 'it.ch'.
*it; //Doesn't access the base iterator; simply returns 'it.ch'.
*it2; //Cannot access 'it.ch', so must access base iterator.
OK, bene, quindi non puoi usare InputIterators. Ma per quanto riguarda ForwardIterator? È possibile creare un adattatore ForwardIterator in grado di adattare ForwardIterators su sequenze di caratteri UTF-8?
Anche questo è problematico, perché l'operazione *it
è richiesta per produrre value_type&
o const value_type&
. InputIterators può sputare tutto ciò che è convertibile in value_type
, ma è necessario un ForwardIterator
per fornire un riferimento effettivo [forward.iterators] /1.3:
if
X
is a mutable iterator,reference
is a reference toT
; ifX
is a constant iterator,reference
is a reference toconst T
L'unica risorsa qui è che ogni iteratore di questo tipo porta in giro un char32_t
, che esiste unicamente per fornire l'archiviazione per quel riferimento. E anche allora, quel valore dovrà essere aggiornato ogni volta che l'istanza iteratore viene incrementata e dereferenziata. Ciò invalida efficacemente il vecchio riferimento e lo standard non lo consente esplicitamente (l'invalidazione può avvenire solo quando un iteratore viene distrutto o se il contenitore lo dice).
Il codice sopra riportato che ho trovato online non è valido a causa di ciò, poiché restituisce un uint32_t
(scritto pre-C ++ 11) per valore anziché un riferimento appropriato.
C'è qualche ricorso qui? Ho trascurato qualcosa nello standard o qualche tecnica di implementazione che potrei usare per aggirare questi problemi? O semplicemente non è possibile con l'attuale formulazione dello standard?
Nota: la cosa strana è che sembra possibile scrivere un OutputIterator conforme per la conversione UTF-8. Ovvero, un tipo che prende char32_t
e scrive UTF-8 in char
o unsigned char
OutputIterator.