Фигурные скобки - это новая инициализация C ++ 11.
.base()
и обратные итераторы
.base()
- это вернуть базовый итератор (back
- это reverse_iterator
), чтобы правильно построить новую строку из допустимого диапазона.
Картинка. Нормальные позиции итератора в строке (это немного сложнее в отношении того, как работает rend()
, но в любом случае концептуально ...)
begin end
v v
-------------------------------------
| sp | sp | A | B | C | D | sp | sp |
-------------------------------------
^ ^
rend rbegin
Как только ваши два цикла поиска закончатся, результат этих итераторов в этой последовательности будет расположен по адресу:
front
v
-------------------------------------
| sp | sp | A | B | C | D | sp | sp |
-------------------------------------
^
back
Если бы мы взяли только эти итераторы и построили из них последовательность (чего мы не можем, поскольку они не соответствуют типам, но независимо от того, что мы предполагали), результатом было бы «копирование, начиная с A, останавливаясь на D». но он не будет включать D в итоговые данные.
Введите back()
член обратного итератора. Он возвращает необратный итератор класса прямого итератора, который располагается в элементе «рядом с» обратным итератором; т.е.
front
v
-------------------------------------
| sp | sp | A | B | C | D | sp | sp |
-------------------------------------
^
back.base()
Теперь, когда мы копируем наш диапазон { front, back.base() }
, мы копируем, начиная с A
и останавливаясь на первом пробеле (но не включая его), тем самым включая букву D, которую мы бы пропустили.
Кстати, это действительно небольшой кусочек кода.
Дополнительная проверка
В исходный код добавлены базовые проверки.
Пытаясь сохранить дух исходного кода (использование C ++ 1y / C ++ 14), добавляя некоторые базовые проверки для пустых строк и строк, содержащих только пробелы;
string trim_check(string const& s)
{
auto is_space = [](char c) { return isspace(c, locale()); };
auto front = find_if_not(begin(s), end(s), is_space);
auto back = find_if_not(rbegin(s), make_reverse_iterator(front), is_space);
return string { front, back.base() };
}
26.06.2014
base()
ссылается на элемент рядом с, на который ссылается обратный итератор. В данном случае это в некоторой степени синонимstd::next(back)
, но не в обратном направлении, а в прямом направлении базовой последовательности. 26.06.2014reverse_iterator
. 26.06.2014back
действительно ссылается на последний непробельный символ. Но если вы включите это какend
итератор копии (или, в вашем случае, конструктор диапазона итераторов), это позиция остановки, и вы на один слот короче (и в любом случае это неправильный итератор типа). Вы не хотите останавливаться на достигнутом, вы хотите остановить один слот после этой позиции. Думайте об этом аналогично тому, какend()
в обычных последовательностях итераторов ссылается на один последний элемент. Помните, что в C ++ конечные точки итератора означают остановку, когда вы попадаете сюда, а не остановку, когда вы проходите здесь. Надеюсь, это имело смысл. 26.06.2014int isspace(int ch)
, которое требует, чтобыch
был представлен какunsigned char
en.cppreference.com/w/c/string/byte/isspace. Лямбда избегает преобразования (которое технически может вызывать неопределенное поведение, хотя я видел, как этот UB аргументировался очень подробно), а лямбда использует более приятный C ++isspace(char, locale)
. Лично я предпочитаю использовать возможности C ++ вместо тех, которые существуют на C, но это только личное. 08.07.2014rbegin()
, например, не существует. 08.07.2014char
из предоставленного аргумента, поэтому вызов функции становитсяisspace(char,locale)
. C ++isspace
с локалью требует, чтобыlocale
был привязан к вызову, поэтому нельзя использовать простой адрес, это можно сделать с помощью лямбда;bind
или одно из связывателей C ++ 98 (bind2nd
и т. Д.). Хороший момент,rbegin
- это средство библиотеки, которое будет введено в C ++ 14, некоторые библиотеки уже реализуют его. Поскольку он был в исходном коде, я сохранил его в образце. 08.07.2014<decltype(front)>
? 07.08.2014