C ++のイテレータカテゴリは、UTF-8イテレータアダプタの作成を禁止していますか?


8

私はUTF-8イテレーターアダプターに取り組んでいます。つまり、イテレータをaに、charまたはunsigned charシーケンスをイテレータからシーケンスに変換するアダプタを意味しchar32_tます。ここでの私の仕事は、オンラインで見つけこのイテレータに触発されました

ただし、独自の実装を開始するときに標準を調べたところ、C ++がイテレータに課す要件に準拠しながら、このようなアダプタを実装することはできないようです。

たとえば、InputIterator要件を満たすUTF-8イテレータを作成できますか?はい。ただし、指定されたイテレータ自体がInputIteratorではない場合に限ります。どうして?

InputIteratorは、同じイテレータを複数回逆参照する機能を必要とするためです。それらがすべて等しい場合、そのイテレータの複数のコピーを逆参照することもできます。

もちろん、UTF-8イテレーターアダプターを逆参照するには、基本イテレーターの逆参照と、場合によっては増分を行う必要があります。そして、そのイテレーターがInputIteratorである場合、元の値をインクリメントした後に戻すことはできません。また、コピーが機能する必要があるという事実char32_tは、以前にデコードされた値を表すをローカルに保存できないことを意味します。あなたはこれを行うことができたでしょう:

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.

わかりました。InputIteratorsは使用できません。しかし、ForwardIteratorはどうでしょうか?UTF-8文字シーケンスでForwardIteratorを適応できるForwardIteratorアダプターを作成することは可能ですか?

またはを生成するに*itは操作が必要なため、これも問題です。InputIteratorsはに変換可能である何かを吐き出すことができますが、[forward.iterators] /1.3実際の参照を提供するために必要とされます。value_type&const value_type&value_typeForwardIterator

Xが可変イテレータである場合、referenceはへの参照Tです。Xが定数イテレータの場合、referenceはへの参照ですconst T

ここでの唯一の手段は、そのようなすべてのイテレータがを持ち運ぶchar32_tことです。これは、その参照用のストレージを提供するためだけに存在します。その場合でも、イテレータインスタンスがインクリメントされ、逆参照されるたびに、その値を更新する必要があります。これは古い参照を事実上無効にし、標準はそれを明示的に許可していません(無効化はイテレータが破棄された場合、またはコンテナがそうした場合にのみ発生します)。

オンラインで見つけた前述のコードuint32_tは、適切な参照ではなく値によって(C ++ 11より前に記述された)値を返すため、これが原因で無効です。

ここに頼ることはありますか?標準の何か、またはこれらの問題を回避するために使用できるいくつかの実装手法を見落としましたか?それとも、現在の標準の文言ではこれはまったく不可能ですか?

注:奇妙なことに、UTF-8変換用の準拠するOutputIteratorを記述できるように思われます。つまり、char32_tUTF-8を受け取って、charまたはunsigned charOutputIteratorに書き込む型です。


3
の表現が、可能ForwardIteratorになったプロキシイテレータなど、あらゆる種類のプロキシイテレータとうまく適合しなかったことはよく知られていますvector<bool>。その決定がなされた理由を説明するハーブサッターによって1999年に書かれた有名な記事がありました。現代では、この問題を再考する傾向がありました。エリックニーブラーが書いたものを見つけました。もっとあるかもしれません。いくつかのC ++提案では、ハーブサッター自身が書いたものもあるかもしれません。
rwong

InputIteratorでは、イテレータを逆参照する前にキャッシュを読み取ることはできませんか?
user253751 2017

@immibis:ええと、何のキャッシュを読みますか?ユーザーが実際に逆参照する前に入力イテレーターから読み取ると、無効なイテレーターにアクセスする可能性があります。イテレーターは、範囲の終わりがどこにあるかを必ずしも認識していないためです。したがって、イテレータをインクリメントしても、逆参照しても問題ないというわけではありません。また、InputIteratorsのコピーに関して私が作成したポイントを覚えておいてください。同じ入力イテレーターの2つのコピーを逆参照すると、同じ値を取得するはずです。
Nicol Bolas

回答:


2

短い答えはイエスだと思います。UTF-8をデコードするイテレーターアダプター(より一般的には、単一の出力アイテムを生成するために複数の入力アイテムが必要になる可能性があります)は、(少なくとも)BidirectionalIteratorをモデル化するイテレーターの上に階層化する必要があります。

これは、定数イテレータのみが必要であると想定していることに注意してください(つまり、入力からUTF-8を読み取るだけで、基になるコレクションにUTF-8を書き込まない)。書き込みをサポートしたい場合、急いで物事は非常に醜くなります-UTF-32レベルである値から別の値に変更すると、異なるサイズのUTF-8エンコーディングが簡単に生成される可能性があるため、準備する必要があります書き込みをサポートする場合は、基になるコレクションの中央にアイテムを挿入/削除します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.