seraphyの日記

日記というよりは過去を振り返るときのための単なる備忘録

const_reverse_iteratorは非constなコンテナからは返せない?

またC++の深遠なる世界にハマる。

コンテナが返すイテレータは、それと同じタイプのイテレータであることしか保障されていないらしい。constなコンテナならconstイテレータ、非constなら非constイテレータ

http://forums.belution.com/ja/cpp/000/010/48s.shtml

VC/GCCの実装ではiteratorとconst_iteratorは比較互換が(たまたま)あるために、非constなイテレータで書き換えが必要ないときにconst_iteratorを使うことは可能だったが、規格的には禁止も保証もされていないundocumentな動作である、と。
つまり、非constなコンテナは、どこまでも非constを貫け、と…。
これは誤認であった。(2006/11訂正)*1
C++仕様的には、非constからconst方向へのイテレータの変換は保証されており、できないのはVC/GCCのバグだったらしい。
ロストしないように引用しておく。

Re[4]:const_reverse_iteratorでエラー 
 
#00001063 (Reply to #00001054)
名前 YuO (メール) 日時 2003-06-18 18:08:35 
> 実際問題 non-const-container な v に v.begin() を取る時、
> 使われるのは begin() であって begin() const ではありません。

でも,iteratorはconst_iteratorに変換可能ですよね。
lib.container.requirementsのTable 65-Container requirementsの,
X::iteratorのところに
>convertible to X::const_iterator
と書いてあります。

また,reverse_iteratorからconst_reverse_iteratorの間の変換についてですが……。

Table 66-Revsersible container requirementsによって,
reverse_iteratorはreverse_iterator<iterator>であり,
const_reverse_iteratorはreverse_iterator<const_iterator>です。

そして,lib.reverse.iteratorに
>template <class U> reverse_iterator(const reverse_iterator<U>& u);
という記述があります。
lib.reverse.iter.consによると,上記コンストラクタは,
currentをu.currentで初期化する,とあります。

iteratorをconst_iteratorに変換できるということから,
const_iteratorをiteratorで初期化することは可能です。

よって,const_reverse_iteratorはreverse_iteratorに変換可能です。


> たまたま VC++ の実装では forward-iterator は const と non-const とで比較互換、
> backward-iterator は const と non-const が比較非互換なだけのようです。
> # gcc-3.2.1 のもそういう実装でした。

こちらに関しては,標準化委員会に欠陥リポート等が上がっています。
http://std.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#179
http://std.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#280

なので,次の版で比較可能になることでしょう。


FDISへのポインタ
lib.container.requirements:
http://www.kuzbass.ru:8086/docs/isocpp/lib-containers.html#lib.container.requirements
lib.reverse.iterator:
http://www.kuzbass.ru:8086/docs/isocpp/lib-iterators.html#lib.reverse.iterators
lib.reverse.iter.cons:
http://www.kuzbass.ru:8086/docs/isocpp/lib-iterators.html#lib.reverse.iter.cons 
 
Re[5]:const_reverse_iteratorでエラー 
 
 
#00001075 (Reply to #00001063)
名前 tetrapod 日時 2003-06-20 00:40:29 
iterator から const-iterator へは変換可能でしたか (メモメモφm)
# 逆は当然だめとして

> よって,const_reverse_iteratorはreverse_iteratorに変換可能です。
本当に?逆ではなくて?
std::const_reverse_iterator<T> cri;
std::reverse_iterator<T> ri;
ri=cri;
が通っちゃうと、これだけで const はがしができちゃいますが。

>> template <class U> reverse_iterator(const reverse_iterator<U>& u);
仮引数が const_reverse_iterator<U>& で無いので異議有り。規格書が主張しているのは
reverse_iterator のコピー生成ができるということかと。

ちょっとチェック STLport-4.5.3 で最初のソースをコンパイル。
おやおや = で代入できないと言ってますね。だめぢゃん > STLport

まあ、規格書に処理系の実装が追いついていないのが C++ の現状ではあるので、
とりあえず今のところは const_reverse_iterator の使用は要注意、
ってとこでしょう。 
 
Re[6]:const_reverse_iteratorでエラー 
 
 
#00001076 (Reply to #00001075)
名前 YuO (メール) 日時 2003-06-20 03:23:46 
>> よって,const_reverse_iteratorはreverse_iteratorに変換可能です。
> 本当に?逆ではなくて?

逆です……書き間違い……。
#校正中に逆になったらしい。 

http://forums.belution.com/ja/cpp/000/010/48s.shtml

*1:日記を読み返して発見。C++は何が正しいのかを見極めるだけでも大変だということを改めて実感。