Форум » C/C++ » Предложение по включению в стандарт C++ итераторов c_str_iterator и const_c_str_iterator » Ответить

Предложение по включению в стандарт C++ итераторов c_str_iterator и const_c_str_iterator

Сыроежка: Нередко приходится выполнять стандартные алгоритмы для C-строк. Чтобы предоставить два итератора, начальный итератор и конечный итератор диапазона, то есть начало и конец строки, для алгоритма приходится вызывать стандартную C-функцию strlen, объявленную в заголовочном файле <cstring>. Например, вызов стандартного алгоритма std::adjacent_find, содержащего строку, может выглядеть следующим образом [pre2] size_t n = ::strlen( s ); char *p = std::adjacent_find( s, s + n ); if ( p != s + n ) std::cout << p << std::endl; [/pre2] Как видно из примера, требуется вызывать стандартную C-функцию strlen, чтобы получить конечный итератор диапазона. Однако все C-строки по определению имеют завершающий ноль-символ '\0', и по этому символу легко определить конец диапазона, если имеешь дело с последовательными итераторами. То есть предварительный вызов функции strlen является неэффективным и избыточным. В связи с этим я предлагаю использовать итераторы, названные мною как const_c_str_iterator и c_str_iterator, которые позволяют применять стандартные алгоритмы к C-строкам без необходимости вызова стандартной C-функции strlen, чтобы задать диапазон итераторов. Ниже приведена демонстрационная программа, в которой показано, как данные итераторы для C-строк могут быть определены. [pre2] #include <iostream> #include <iterator> #include <algorithm> class const_c_str_iterator { public: using iterator_category = std::forward_iterator_tag; using value_type = char; using difference_type = ptrdiff_t; using pointer = const char *; using reference = const char &; // Constructors const_c_str_iterator() = default; explicit const_c_str_iterator( const char *s ) : s( s ) { } const_c_str_iterator( const const_c_str_iterator & ) = default; // The copy assignment operator const_c_str_iterator & operator =( const const_c_str_iterator &it ) { this->s = it.s; return *this; } // Conversion operator operator pointer() const { return s; } // Increment operators const_c_str_iterator & operator ++() { ++this->s; return *this; } const_c_str_iterator operator ++( int ) { const_c_str_iterator it( this->s ); ++this->s; return it; } // Dereferencing operator reference operator *() const { return *s; } friend bool operator ==( const const_c_str_iterator &it1, const const_c_str_iterator &it2 ); friend bool operator !=( const const_c_str_iterator &it1, const const_c_str_iterator &it2 ); protected: const char *s = nullptr; }; bool operator ==( const const_c_str_iterator &it1, const const_c_str_iterator &it2 ) { return ( it1.s == it2.s ) || ( not it1.s && not *it2.s ) || ( not *it1.s && not it2.s ); } bool operator !=( const const_c_str_iterator &it1, const const_c_str_iterator &it2 ) { return not ( it1 == it2 ); } class c_str_iterator { public: using iterator_category = std::forward_iterator_tag; using value_type = char; using difference_type = ptrdiff_t; using pointer = char *; using reference = char &; // Constructors c_str_iterator() = default; explicit c_str_iterator( char *s ) : s( s ) { } c_str_iterator( const c_str_iterator & ) = default; // The copy assignment operator c_str_iterator & operator =( const c_str_iterator &it ) { this->s = it.s; return *this; } // Conversion operators operator pointer() const { return s; } operator const_c_str_iterator() const { return const_c_str_iterator( this->s ); } // Increment operators c_str_iterator & operator ++() { ++this->s; return *this; } c_str_iterator operator ++( int ) { c_str_iterator it( this->s ); ++this->s; return it; } // Dereferencing operator reference operator *() const { return *s; } friend bool operator ==( const c_str_iterator &it1, const c_str_iterator &it2 ); friend bool operator !=( const c_str_iterator &it1, const c_str_iterator &it2 ); protected: char *s = nullptr; }; bool operator ==( const c_str_iterator &it1, const c_str_iterator &it2 ) { return ( it1.s == it2.s ) || ( not it1.s && not *it2.s ) || ( not *it1.s && not it2.s ); } bool operator !=( const c_str_iterator &it1, const c_str_iterator &it2 ) { return not ( it1 == it2 ); } int main() { { char s[] = "Aa Bb Cc Dd"; const char *t = "Cc"; auto it = std::adjacent_find( c_str_iterator( s ), {}, [=]( char c1, char c2 ) { return c1 == t[0] && c2 == t[1]; } ); if ( it != c_str_iterator() ) std::cout << it << std::endl; } { const char *s = "Aa Bb Cc Dd"; const char *t = "Cc"; auto it = std::adjacent_find( const_c_str_iterator( s ), {}, [=]( char c1, char c2 ) { return c1 == t[0] && c2 == t[1]; } ); if ( it != const_c_str_iterator() ) std::cout << it << std::endl; } } [/pre2] Вывод программы на консоль [pre2] Cc Dd Cc Dd [/pre2]

Ответов - 0



полная версия страницы