std::string
C++0x の と文字列リテラルの間に不穏な矛盾があることを発見しました。
#include <iostream>
#include <string>
int main()
{
int i = 0;
for (auto e : "hello")
++i;
std::cout << "Number of elements: " << i << '\n';
i = 0;
for (auto e : std::string("hello"))
++i;
std::cout << "Number of elements: " << i << '\n';
return 0;
}
出力は次のとおりです。
Number of elements: 6
Number of elements: 5
これが発生する理由のメカニズムを理解しています。文字列リテラルは実際には null 文字を含む文字の配列であり、範囲ベースの for ループがstd::end()
文字配列を呼び出すと、配列の末尾を超えてポインターが取得されます。ヌル文字は配列の一部であるため、ヌル文字を超えるポインターを取得します。
ただし、これは非常に望ましくないと思います。確かにstd::string
、文字列リテラルは、長さと同じくらい基本的なプロパティに関しては同じように動作する必要がありますか?
この矛盾を解決する方法はありますか? たとえば、文字配列std::begin()
をstd::end()
オーバーロードして、それらが区切る範囲に終端の null 文字が含まれないようにすることはできますか? もしそうなら、なぜこれが行われなかったのですか?
編集:「レガシー機能」であるCスタイルの文字列を使用した結果に苦しんでいると言っている人たちに私の憤りをもう少し正当化するために、次のようなコードを検討してください:
template <typename Range>
void f(Range&& r)
{
for (auto e : r)
{
...
}
}
あなたは何か違うことを期待f("hello")
し、f(std::string("hello"))
するでしょうか?