Le categorie di iteratore di C ++ impediscono di scrivere un adattatore iteratore UTF-8?

8

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 to T ; if X is a constant iterator, reference is a reference to const 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.

    
posta Nicol Bolas 01.04.2017 - 20:43
fonte

1 risposta

3

Penso che la risposta breve sia sì. Un adattatore iteratore che decodifica UTF-8 (e più in generale, che potenzialmente richiede più elementi di input per produrre un singolo elemento di output) deve essere sovrapposto a un iteratore che modella (almeno) BidirectionalIterator.

Si noti che si presume che si voglia solo un iteratore costante (cioè, si legge solo UTF-8 dall'input, non si scrive UTF-8 nella raccolta sottostante). Se vuoi supportare la scrittura, le cose diventano molto più brutte in fretta: il passaggio da un valore all'altro a livello UTF-32 può facilmente produrre una codifica UTF-8 che ha una dimensione diversa, quindi devi essere preparato per inserire / eliminare elementi nel mezzo della raccolta sottostante, se avevi intenzione di supportare la scrittura.

    
risposta data 04.04.2017 - 17:10
fonte

Leggi altre domande sui tag