Open GeorgiiFirsov opened 3 years ago
Я бы оставил пользователю возможность передавать свой предикат для этих функций
Или хотя бы массив символов (но для этого придется делать эту мембер функцию шаблонной, что приведет к str.template trim(chars...)
), как в других языках:
C#: https://docs.microsoft.com/en-us/dotnet/api/system.string.trim?view=net-5.0#overloads
Python: https://docs.python.org/3.4/library/stdtypes.html?highlight=strip#str.lstrip
Возможно, стоит сделать по аналогии с erase
и erase_if
, что-то типа:
template <typename Char, typename Traits, typename Allocator, std::predicate<Char> Predicate>
typename std::basic_string<Char, Traits, Allocator>::size_type trim_if(std::basic_string<Char, Traits, Allocator>& str, Predicate&& predicate);
template <typename Char, typename Traits, typename Allocator, typename... Chars>
requires std::convertible_to<Chars, Char> && ...
typename std::basic_string<Char, Traits, Allocator>::size_type trim(std::basic_string<Char, Traits, Allocator>& str, Chars&&... chars);
Немного неясны несколько моментов:
trim[_if]
должны возвращать size_type
? Логичнее возвращать ссылку на себя, как в моем оригинальном предложении.constexpr size_type find_first_of( const CharT* s, size_type pos = 0 ) const;
constexpr size_type find_first_not_of( const CharT* s, size_type pos = 0 ) const;
...
Суть параметра s
ровно такая же. Да и как-то уж больно странно будет вот так использовать функцию:
str.trim(' ', '\t', '\n');
В итоге то никаких темплейтных мемберов и не получается (что хорошо):
constexpr basic_string& trim();
constexpr basic_string& trim(const char_type* s);
// trim_left и trim_right аналогично
Почему trim[_if] должны возвращать size_type? Логичнее возвращать ссылку на себя, как в моем оригинальном предложении.
Делал по аналогии с
erase[_if]
: функция возвращает количество удаленных элементов
constexpr basic_string& trim(const char_type* s);
Тогда уж лучше принимать
std::basic_string_view
: чтобы перенести бремя UB с отсутствием'\0'
или вообщеs == nullptr
на пользователя.В итоге то никаких темплейтных мемберов и не получается (что хорошо)
Считаю, что
trim_if
(и по аналогии другие тоже) должны всё-таки существовать, и их придётся делать шаблонами.
И ещё предлагаю не забывать про аналогичные функции для `str::basic_string_view
Делал по аналогии с erase[_if]: функция возвращает количество удаленных элементов
Есть нюанс. Тот же erase
не предполагает использования её результата прямо на месте, а вот trim
выглядит очень органично в таком контексте:
std::string some_input = ...;
ProcessInput(some_input.trim());
trim
надо скорее сопоставлять с substr
(чем в сущности он и является).
Тогда уж лучше принимать std::basic_string_view
Лучше для консистентности тут поступить тогда, как в уже упомянутых find_first_of
и иже с ней:
constexpr size_type find_first_of( const CharT* s, size_type pos = 0 ) const;
template < class T >
constexpr size_type find_first_of( const T& t, size_type pos = 0 ) const noexcept(/* see below */);
При этом последняя имеет следующее описание:
Implicitly converts t to a string view sv as if by
std::basic_string_view<CharT, Traits> sv = t;
, then finds the first character equal to one of the characters in sv. This overload participates in overload resolution only ifstd::is_convertible_v<const T&, std::basic_string_view<CharT, Traits>>
istrue
andstd::is_convertible_v<const T&, const CharT*>
isfalse
.
Это что касается basic_string_view
, далее имеет смысл добавить перегрузки для char_type
и basic_string
.
Суть
Добавить в шаблон класса строки методы
trim_left
,trim_right
иtrim
, которые обрезают пробельные символы слева, справа или по обеим сторонам строчки.Применение
Полезно, к примеру, при построчном чтении файлов, при обработке ввода от пользователя и тому подобных случаях. Часто на моей практике встречаются ситуации, когда пробельные символы по сторонам строчки необходимо убрать.
Пример реализации
Возможная реализация
Как можно сейчас