次のコードについて考えてみます。
_#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec{1,2,3,5};
for(auto it=vec.cbegin();it!=vec.cend();++it)
{
std::cout << *it;
// A typo: end instead of cend
if(next(it)!=vec.end()) std::cout << ",";
}
std::cout << "\n";
}
_
ここでタイプミスを紹介しました。比較では、vec.end()
ではなくvec.cend()
と呼びました。これは、gcc5.2で意図したとおりに機能するようです。しかし、それは実際には規格に従って明確に定義されていますか? iterator
と_const_iterator
_を安全に比較できますか?
驚いたことに、C++ 98とC++ 11は、iterator
をconst_iterator
と比較できるとは言っていませんでした。これにより、 LWG問題179 および LWG問題226 になります。現在C++ 14では、これは§23.2.1[container.requirements.general] p7によって明示的に許可されています。
式で
i == j i != j i < j i <= j i >= j i > j i - j
ここで、
i
とj
は、コンテナのiterator
タイプのオブジェクトを示し、いずれかまたは両方を、同じ要素を参照するコンテナのconst_iterator
タイプのオブジェクトに置き換えることができます。セマンティクスに変更はありません。
C++ 11標準の表96のセクション23.2.1では、任意のコンテナタイプX
(std::vector
を含む)のa.cend()
の操作的意味論を次のように定義しています。
const_cast<X const &>(a).end()
したがって、この定義ではcend()
はend()
と同じコンテナ内の要素/位置を参照し、X::iterator
はX::const_iterator
(a同じ表で指定されている要件(*))。
(同じ表で定義されているのと同じ理由で、begin()
とcbegin()
の答えも「はい」です。)
(*) 他の回答へのコメントで、兌換性は必ずしも比較操作i1==i2
が常に機能することを意味するわけではないことが指摘されています。 operator==()
がイテレータ型のメンバー関数である場合、暗黙的な変換は、左側の引数ではなく、右側の引数に対してのみ受け入れられます。 24.2.5/6状態(フォワードイテレータa
およびb
について):
a
とb
の両方が逆参照可能である場合、a == b
と*a
が同じオブジェクトにバインドされている場合に限り、*b
イテレータend()
とcend()
は参照解除できませんが、上記のステートメントは、a
がconstであっても、比較が可能なようにoperator==()
を定義する必要があることを意味します。 -iteratorとb
はそうではなく、その逆も同様です。24.2.5は、constバージョンとnon-constバージョンの両方を含む一般的なフォワードイテレーターに関するものだからです。 24.2.5/1から。これが、兌換性を指す表96の文言も、比較可能性を意味すると確信している理由です。しかし、cpplearner @の後の回答で説明されているように、これはC++ 14でのみ明示的に明確にされています。
§23.2.1、表96を参照してください。
X::iterator
[...]
フォワードイテレータの要件を満たすイテレータカテゴリ。
X::const_iterator
に変換可能
だから、はい、それは明確に定義されています。