std::string::iterator は何型 ?
発端
Borland C++ Buider 6 で作っていたあるプログラムをgccでコンパイルしようとしたら、コンパイルが通らなかった。問題の箇所は一言で言うと、次のようなコードとなっていました。
std::string s;
// 中略br>
char *p = s.begin();
puts(p);
std::string::begin() の返す方は std::string::iterator 型であるので、この時点で相当阿漕なコードではあるのだが、それでも C++ Builder では何の問題もなくコンパイルできていた。
そこで、手元にあるコンパイラで上記のコードをコンパイルしてみた。
メーカー
|
製品
|
バージョン
|
STL
|
結果
|
Borland
|
C++ Builder |
6 |
STLPort |
OK |
Borland
|
C++ Builder
|
6
|
RogueWave
|
OK
|
Microsoft
|
Visual C++
|
6
|
Dikumware
|
OK
|
cygwin
|
g++
|
3.2
|
libstdc++
|
NG
|
実際の定義
実際の定義はどうなっているかというと
C++ Buider (STLPort)
template <class _CharT, class _Traits, class _Alloc> class basic_string
: protected _String_base<_CharT,_Alloc> {
...
typedef _CharT value_type;
...
typedef value_type* pointer;
typedef value_type* iterator;
}
よって string の場合、iterator は char * と同じ型となります。
C++ Builder 6 (RogueWave)
template <class charT, class traits , class Allocator >
class _RWSTDExportTemplate basic_string {
typedef
charT*
iterator;
}
となり string の場合、iterator は char * と同じ型となります。
Visual C++ 6 の場合
template<class _E,
class _Tr = char_traits<_E>,
class _A = allocator<_E> >
class basic_string {
typedef _A::pointer pointer;
typedef _A::pointer iterator;
}
となっており、allocator クラスでは
template<class _Ty>
class allocator {
typedef _Ty _FARQ *pointer;
}
となっているので、結局 string の場合は char * となります。
g++ の場合
template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string {
typedef __gnu_cxx::__normal_iterator<pointer, basic_string> iterator;
}
となっており、結局 __gnu_cxx::__normal_iterator<pointer, basic_string>となっています。
これでは char * には(何かしらの変換関数が用意されていない限り)到底変換できません。
結論
- 阿漕なコードは書くな。
- iterator 型は iterator 型であって、ほかの何者でもありません。
[覚書]
[トップページ]