C++11から、SCARYイテレータ(怖いイテレータ)という規定が入りました。
SCARYというのは「Seemingly erroneous (Constrained by conflicting generic parameters), but Actually work with the Right implementation (unconstrained bY the conflict due to minimized dependencies).」の略で、「(競合するテンプレートパラメータによって制約されるから)一見間違ったコードに見えるけど、(依存関係の最小化によって)実際には正しく動く」という意味です。
こじつけ感満載の略語ですが、これは以下のようなものです。
vector<int> v1; vector<int, MyAllocator<int>> v2; decltype(v1)::iterator it = v1.begin(); it = v2.begin(); // OK
つまり、標準コンテナのイテレータの依存関係を最小化し、異なるアロケータのイテレータ同士でも代入可能にしよう、というものです。イテレータはアロケータを使わないので、コンパイルを通してしまっていいだろう、と。
この依存関係の最小化はアロケータのみならず、set
やmap
の比較演算子、unordered連想コンテナのハッシュ関数も対象になります。
Clangは3.1から、VCは2012(11.0)からSCARYイテレータをサポートしています。GCCは4.8時点でまだ対応していません。Boost.Containerは1.55.0からこれをサポートしています。以下、実際に動くコード:
#include <vector> template <class T> struct MyAllocator { using value_type = T; static T* allocate(std::size_t n) { return new T[n]; } static void deallocate(T* pointer, std::size_t n) { static_cast<void>(n); delete[] pointer; } }; int main() { std::vector<int> v1; std::vector<int, MyAllocator<int>> v2; decltype(v1)::iterator it = v1.begin(); it = v2.begin(); }