Я обнаружил тревожную несогласованность между std::string
и строковыми литералами в С++ 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
Я понимаю механику, почему это происходит: строковый литерал - это действительно массив символов, который включает нулевой символ, и когда цикл на основе цикла вызывает std::end()
в массиве символов, он получает указатель мимо конец массива; поскольку нулевой символ является частью массива, он, таким образом, получает указатель за нулевым символом.
Однако, я думаю, что это очень нежелательно: неужели std::string
и строковые литералы должны вести себя одинаково, когда дело касается свойств как основных, как их длина?
Есть ли способ разрешить эту несогласованность? Например, могут ли быть перегружены std::begin()
и std::end()
для массивов символов, так что диапазон, который они ограничивают, не включает завершающий нулевой символ? Если да, почему это не было сделано?
EDIT. Чтобы оправдать мое негодование немного больше тем, кто сказал, что я просто страдаю последствиями использования строк стиля С, которые являются "устаревшей функцией", рассмотрите код, подобный следующее:
template <typename Range>
void f(Range&& r)
{
for (auto e : r)
{
...
}
}
Ожидаете ли вы, что f("hello")
и f(std::string("hello"))
сделать что-то другое?