Фигурные скобки - это новая инициализация 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 charen.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