cstring_iterator
От: igna Россия  
Дата: 11.07.11 14:22
Оценка:
Нужен итератор по знакам/символам строки заканчивающейся нулем (без предварительного измерения длины строки), который будет использоваться примерно так:

template <class OutputIterator>
void copy_cstring(char const* s, OutputIterator oi)
{
    copy(cstring_iterator(s), cstring_iterator(), oi);
}


Boost смотрел, не нашел. Хорошо запрятали (как например implicit_cast), плохо смотрел, или авторам не до таких мелочей?

В общем нужно приблизительно вот что:

class cstring_iterator : public iterator<forward_iterator_tag, char> {
    char const* ptr_;
    char value_;

    void read_value()
    {
        value_ = *ptr_;
        if (!value_)
            ptr_ = 0;
    }
public:
    explicit cstring_iterator(char const* const s)
        : ptr_ (s)
    {
        read_value();
    }
    cstring_iterator()
        : ptr_ (0)
    {}
    char operator*()
    {
        return value_;
    }
    cstring_iterator& operator++()
    {
        ++ptr_;
        read_value();
        return *this;
    }
    cstring_iterator operator++(int)
    {
        cstring_iterator tmp;
        operator++();
        return tmp;
    }
    friend bool operator==(cstring_iterator const& x, cstring_iterator const& y)
    {
        return x.ptr_ == y.ptr_;
    }
    friend bool operator!=(cstring_iterator const& x, cstring_iterator const& y)
    {
        return !operator==(x, y);
    }
};
Re: cstring_iterator
От: c-smile Канада http://terrainformatica.com
Дата: 11.07.11 15:20
Оценка:
Здравствуйте, igna, Вы писали:

Или я не понял или ты только что описал банальный указатель const char* и его встроенный operator++.
Только зачем этот весь огород? Чисто чтоб было как у пацанов в boost?
Re[2]: cstring_iterator
От: _nn_ www.nemerleweb.com
Дата: 11.07.11 15:45
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, igna, Вы писали:


CS>Или я не понял или ты только что описал банальный указатель const char* и его встроенный operator++.

CS>Только зачем этот весь огород? Чисто чтоб было как у пацанов в boost?

Получится такой простой универсальный код:
template <class InputPointer, class OutputIterator>
void copy_cstring(InputPointer s, OutputIterator oi)
{
    while (*s)
    {
        *oi = *s;
        ++oi;
        ++s;
    }
}


Но тогда нет begin и end
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: cstring_iterator
От: wander  
Дата: 11.07.11 20:36
Оценка: 1 (1) +1
Здравствуйте, igna, Вы писали:

I>Нужен итератор по знакам/символам строки заканчивающейся нулем (без предварительного измерения длины строки), который будет использоваться примерно так:


здесь
Re[2]: cstring_iterator
От: igna Россия  
Дата: 12.07.11 05:51
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Или я не понял или ты только что описал банальный указатель const char* и его встроенный operator++.

CS>Только зачем этот весь огород? Чисто чтоб было как у пацанов в boost?

Чтобы как в STL. И чтобы использовать алгоритмы оттуда.
Re[2]: cstring_iterator
От: igna Россия  
Дата: 12.07.11 08:41
Оценка:
Здравствуйте, wander, Вы писали:

W>здесь


Спасибо, я понял так, что нужно использовать алгоритмы Boost.Range взамен алгоритмов STL. Хорошо, только чего-то подобного cstring_range я в Boost.Range не нашел.
Re[3]: cstring_iterator
От: wander  
Дата: 12.07.11 09:44
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, wander, Вы писали:


W>>здесь


I>Спасибо, я понял так, что нужно использовать алгоритмы Boost.Range взамен алгоритмов STL. Хорошо, только чего-то подобного cstring_range я в Boost.Range не нашел.


Алгоритмы можно и стандартные использовать. ИМХО, range только дополняет их. boost::iterator_range видел?

Нашелся еще вот такой исходник. Что-то подобное встречалось и с использованием range, с ходу не нашел примера.
Re[4]: cstring_iterator
От: igna Россия  
Дата: 12.07.11 10:08
Оценка:
Здравствуйте, wander, Вы писали:

W>Алгоритмы можно и стандартные использовать. ИМХО, range только дополняет их. boost::iterator_range видел?


W>Нашелся еще вот такой исходник. Что-то подобное встречалось и с использованием range, с ходу не нашел примера.


Прошу прощения, можно сначала один вопрос прежде чем я снова начну искать в Bopost.Range. Мне cstring_iterator или cstring_range все-равно придется самому писать?
Re: cstring_iterator
От: Alexander G Украина  
Дата: 12.07.11 14:02
Оценка: 1 (1) +1
Здравствуйте, igna, Вы писали:

I>Нужен итератор по знакам/символам строки заканчивающейся нулем (без предварительного измерения длины строки), который будет использоваться примерно так:


I>
I>template <class OutputIterator>
I>void copy_cstring(char const* s, OutputIterator oi)
I>{
I>    copy(cstring_iterator(s), cstring_iterator(), oi);
I>}
I>


Насколько я вижу, можно написать наследник boost::iterator_adaptor перекрыв только метод equal, это не очень много кода.
Русский военный корабль идёт ко дну!
Re[3]: cstring_iterator
От: jazzer Россия Skype: enerjazzer
Дата: 13.07.11 03:48
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, wander, Вы писали:


W>>здесь


I>Спасибо, я понял так, что нужно использовать алгоритмы Boost.Range взамен алгоритмов STL


Необязательно, хоть и удобно.
Можно юзать вот так:
std::for_each( boost::begin(xxx), boost::end(xxx), yyy );

где xxx — это любой совместимый Forward Iterator Range, включая std::pair<const char*,const char*>.

I>Хорошо, только чего-то подобного cstring_range я в Boost.Range не нашел.

вышеупомянутая std::pair — это оно и есть.
Ну и as_literal(), as_array() тоже их генерят (только у последнего будет ноль заключительный еще):
http://www.boost.org/doc/libs/1_47_0/libs/range/doc/html/range/reference/concept_implementation/semantics/functions.html
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: cstring_iterator
От: igna Россия  
Дата: 13.07.11 04:49
Оценка:
Здравствуйте, jazzer, Вы писали:

I>>Хорошо, только чего-то подобного cstring_range я в Boost.Range не нашел.


J>вышеупомянутая std::pair — это оно и есть.

J>Ну и as_literal(), as_array() тоже их генерят (только у последнего будет ноль заключительный еще):
J>http://www.boost.org/doc/libs/1_47_0/libs/range/doc/html/range/reference/concept_implementation/semantics/functions.html

Они все предварительно измеряют длину строки, верно?
Re: cstring_iterator
От: ioni Россия  
Дата: 13.07.11 06:23
Оценка:
Здравствуйте, igna, Вы писали:

I>Нужен итератор по знакам/символам строки заканчивающейся нулем (без предварительного измерения длины строки), который будет использоваться примерно так:

вы фактически и написали что вам тербуется
я бы подкорректировал так

template < typename TChar >
struct const_string_iterator : public std::iterator< std::forward_iterator_tag, TChar>
{
    TChar const* str_;
    explicit const_string_iterator( TChar const* str ) : str_( str )
    {
    }
    const_string_iterator( ) : str_( 0 )
    {
    }
    TChar operator* ()
    {
        return (str_ == 0) ? 0 : *str_;
    }
    const_string_iterator& operator++()
    {
        if(str_ != 0)
        {
            ++str_;
            if(*str_ == 0) str_ = 0;
        }
        return *this;
    }
    const_string_iterator operator++(int)
    {
        const_string_iterator tmp;
        operator++();
        return tmp;
    }
    friend bool operator==(const_string_iterator const& x, const_string_iterator const& y)
    {
        return x.str_ == y.str_;
    }

    friend bool operator!=(const_string_iterator const& x, const_string_iterator const& y)
    {
        return !operator==(x, y);
    }
};

typedef const_string_iterator< char > char_string_iterator;
typedef const_string_iterator< wchar_t > wchar_string_iterator;

//////////////////////////////////////////////////////////////////////////
int main(int argc, _TCHAR* argv[])
{
    const char* str = {"abcdefghijklmniop"};
    std::copy( char_string_iterator(str), char_string_iterator(), std::ostream_iterator<char>(std::cout, "\n") );
    return 0;
}
Re[5]: cstring_iterator
От: jazzer Россия Skype: enerjazzer
Дата: 13.07.11 06:57
Оценка: 1 (1)
Здравствуйте, igna, Вы писали:

I>Здравствуйте, jazzer, Вы писали:


I>>>Хорошо, только чего-то подобного cstring_range я в Boost.Range не нашел.


J>>вышеупомянутая std::pair — это оно и есть.

J>>Ну и as_literal(), as_array() тоже их генерят (только у последнего будет ноль заключительный еще):
J>>http://www.boost.org/doc/libs/1_47_0/libs/range/doc/html/range/reference/concept_implementation/semantics/functions.html

I>Они все предварительно измеряют длину строки, верно?


иначе random access не получить

но as_array() не должен измерять, просто должен взять весь массив как есть.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: cstring_iterator
От: _nn_ www.nemerleweb.com
Дата: 13.07.11 07:04
Оценка: 1 (1)
Здравствуйте, jazzer, Вы писали:

J>иначе random access не получить


Автору поста очевидно нужен Input/Output итератор, а не Random Access.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: cstring_iterator
От: igna Россия  
Дата: 13.07.11 08:14
Оценка:
Здравствуйте, jazzer, Вы писали:

J>иначе random access не получить


Мне достаточно получить итератор ввода.

J>но as_array() не должен измерять, просто должен взять весь массив как есть.


В моем примере использования того, что нужно, массива нет, так char const*.

Но все-равно за ответ спасибо, нет значит в бусте, того что мне надо в готовом виде.
Re[2]: cstring_iterator
От: igna Россия  
Дата: 13.07.11 08:42
Оценка:
Здравствуйте, ioni, Вы писали:

I>я бы подкорректировал так


У тебя ошибка, в случае пустой строки выводится завершающий строку '\0'.

Не стану утверждать, что у меня ошибок нет; как раз для того, чтобы не выискивать их, и хотел воспользоваться готовым решением. А нафигачить горы непроверенного и неотлаженного кода вдоль и поперек по диагонали я тоже могу. Но не хочу.
Re[3]: cstring_iterator
От: ioni Россия  
Дата: 13.07.11 12:51
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, ioni, Вы писали:


I>>я бы подкорректировал так


I>У тебя ошибка, в случае пустой строки выводится завершающий строку '\0'.


I>Не стану утверждать, что у меня ошибок нет; как раз для того, чтобы не выискивать их, и хотел воспользоваться готовым решением. А нафигачить горы непроверенного и неотлаженного кода вдоль и поперек по диагонали я тоже могу. Но не хочу.


Я проверял нет

int main()
{
    const char* str = {"abcdefghijklmniop"};
//    std::copy( char_string_iterator(str), char_string_iterator(), std::ostream_iterator<char>(std::cout, "\n") );
    size_t len = 0;
    char_string_iterator i = char_string_iterator(str), e =char_string_iterator();
    for(; i != e; ++i)
    {
        char ch = *i;
        ++len;
    }
    std::cout << strlen(str) << " " << len;
 
    return 0;
}
17 17
Re[3]: cstring_iterator
От: ioni Россия  
Дата: 13.07.11 12:54
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, ioni, Вы писали:


I>>я бы подкорректировал так


I>У тебя ошибка, в случае пустой строки выводится завершающий строку '\0'.


I>Не стану утверждать, что у меня ошибок нет; как раз для того, чтобы не выискивать их, и хотел воспользоваться готовым решением. А нафигачить горы непроверенного и неотлаженного кода вдоль и поперек по диагонали я тоже могу. Но не хочу.


точно
сейчас поправлю
Re[3]: cstring_iterator
От: ioni Россия  
Дата: 13.07.11 12:59
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, ioni, Вы писали:


I>>я бы подкорректировал так


I>У тебя ошибка, в случае пустой строки выводится завершающий строку '\0'.


I>Не стану утверждать, что у меня ошибок нет; как раз для того, чтобы не выискивать их, и хотел воспользоваться готовым решением. А нафигачить горы непроверенного и неотлаженного кода вдоль и поперек по диагонали я тоже могу. Но не хочу.


испрвленный конструктор

    explicit const_string_iterator( TChar const* str ) : str_( str )
    {
        if( str_ != 0 && *str_ == 0 ) str_ = 0;
    }
Re[4]: cstring_iterator
От: igna Россия  
Дата: 13.07.11 14:17
Оценка:
Здравствуйте, ioni, Вы писали:

I>испрвленный конструктор


I>    explicit const_string_iterator( TChar const* str ) : str_( str )
I>    {
I>        if( str_ != 0 && *str_ == 0 ) str_ = 0;
I>    }


Хорошо, едем дальше. Проверка str_ != 0 в операторах разыменовывания и инкрементирования in release mode не нужна, поскольку сингулярный итератор разыменовывать и инкрементировать запрещено.
Re[5]: cstring_iterator
От: ioni Россия  
Дата: 14.07.11 05:35
Оценка:
Здравствуйте, igna, Вы писали:

I>Хорошо, едем дальше. Проверка str_ != 0 в операторах разыменовывания и инкрементирования in release mode не нужна, поскольку сингулярный итератор разыменовывать и инкрементировать запрещено.


да пожалуй вы правы
валидность указателя надо проверять до
Re[6]: cstring_iterator
От: Alexander G Украина  
Дата: 14.07.11 07:57
Оценка: 3 (1)
Здравствуйте, ioni, Вы писали:

I>да пожалуй вы правы

I>валидность указателя надо проверять до

Ещё, operator* () должен возвращать ссылку.
Русский военный корабль идёт ко дну!
Re[7]: cstring_iterator
От: ioni Россия  
Дата: 14.07.11 08:06
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, ioni, Вы писали:


I>>да пожалуй вы правы

I>>валидность указателя надо проверять до

AG>Ещё, operator* () должен возвращать ссылку.


тогда уж const
    TChar const& operator* () const
    {
        return *str_;
    }
Re[8]: cstring_iterator
От: ioni Россия  
Дата: 14.07.11 08:16
Оценка:
Здравствуйте, ioni, Вы писали:

ну и postincrement до кучи

    const_string_iterator operator++( int )
    {
        const_string_iterator tmp = *this;
        ++*this;
        return tmp;
    }


предварительно окончательный вариант
template < typename TChar >
struct const_string_iterator : public std::iterator< std::forward_iterator_tag, TChar >
{
    TChar const* str_;
    explicit const_string_iterator( TChar const* str ) : str_( *str == 0 ? 0 : str )
    {
    }
    const_string_iterator( ) : str_( 0 )
    {
    }
    TChar const& operator* () const
    {
        return *str_;
    }
    const_string_iterator& operator++()
    {
        ++str_;
        if (*str_ == 0) str_ = 0;
        return *this;
    }
    const_string_iterator operator++( int )
    {
        const_string_iterator tmp = *this;
        ++*this;
        return tmp;
    }
    //////////////////////////////////////////////////////////////////////////
    friend bool operator==(const_string_iterator const& x, const_string_iterator const& y)
    {
        return x.str_ == y.str_;
    }

    friend bool operator!=(const_string_iterator const& x, const_string_iterator const& y)
    {
        return !operator==(x, y);
    }

};

typedef const_string_iterator< char > char_string_iterator;
typedef const_string_iterator< wchar_t > wchar_string_iterator;

//
int main()
{
    const char* str = {"abcd"};
    std::copy( char_string_iterator(str), char_string_iterator(), std::ostream_iterator<char>(std::cout, "\n") );
    //
    const char* str2 = {""};
    size_t len = std::distance( char_string_iterator(str2), char_string_iterator() );
    std::cout << strlen(str2) << " " << len;
    //    
    return 0;
}
Re[9]: cstring_iterator
От: ioni Россия  
Дата: 14.07.11 08:22
Оценка:
Здравствуйте, ioni, Вы писали:

I>Здравствуйте, ioni, Вы писали:


вот так postincrement не вылетает

    const_string_iterator operator++( int )
    {
        const_string_iterator tmp = *this;
        if( tmp.str_ ) operator++();
        return tmp;
    }
Re[10]: cstring_iterator
От: Alexander G Украина  
Дата: 14.07.11 08:57
Оценка: 3 (1)
Здравствуйте, ioni, Вы писали:

I>
I>    const_string_iterator operator++( int )
I>    {
I>        const_string_iterator tmp = *this;
I>        if( tmp.str_ ) operator++();
I>        return tmp;
I>    }

I>


Вот поэтому автору и нужен готовый итератор.

Вот на основе почти готового:

#include <boost/iterator/iterator_adaptor.hpp>

class cstring_iterator
    : public boost::iterator_adaptor<
        cstring_iterator,
        char const *,
        boost::use_default,
        boost::forward_traversal_tag>
{
public:
    explicit cstring_iterator(char const * buffer = 0)
        : iterator_adaptor_(buffer)
    {
    }

    void increment()
    {
        if ( *base_reference() )
        {
            ++base_reference();
        }
        else
        {
            base_reference() = 0;
        }
    }

    friend class boost::iterator_core_access;
};


не проверял, но ошибок, скорее всего, меншье будет.
Русский военный корабль идёт ко дну!
Re[11]: cstring_iterator
От: ioni Россия  
Дата: 14.07.11 09:16
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>не проверял, но ошибок, скорее всего, меншье будет.

согласен
но вообще то не собирается
Re[12]: cstring_iterator
От: Alexander G Украина  
Дата: 14.07.11 09:37
Оценка:
Здравствуйте, ioni, Вы писали:

I>согласен

I>но вообще то не собирается

Всё собирается. Исправил ошибку, вот:

http://codepad.org/7HVj94bg
Русский военный корабль идёт ко дну!
Re[13]: cstring_iterator
От: ioni Россия  
Дата: 14.07.11 10:07
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, ioni, Вы писали:


I>>согласен

I>>но вообще то не собирается

AG>Всё собирается. Исправил ошибку, вот:


AG>http://codepad.org/7HVj94bg

нет ничего совершенного

int main()
{
    const char* str = {"abcd"};
    std::copy( сstring_iterator(str), cstring_iterator(0), std::ostream_iterator<char>(std::cout, "\n") );
    size_t len = std::distance( cstring_iterator(str), cstring_iterator() );
    std::cout << strlen(str) << " " << len; //добавляет лишний символ
    //
    сstring_iterator s = cstring_iterator(str) + 1; //не собираается
    std::copy( s, cstring_iterator(), std::ostream_iterator<char>(std::cout, "\n") );
    //
    const char* str2 = {""};
    std::copy( cstring_iterator(str2), cstring_iterator(0), std::ostream_iterator<char>(std::cout, "\n") );
    len = std::distance( cstring_iterator(str2), cstring_iterator() );
    std::cout << strlen(str2) << " " << len;//добавляет лишний символ
    //    
    return 0;
}
Re[14]: cstring_iterator
От: jazzer Россия Skype: enerjazzer
Дата: 14.07.11 10:29
Оценка:
Здравствуйте, ioni, Вы писали:

I>
I>    сstring_iterator s = cstring_iterator(str) + 1; //не собираается
I>


и не должно — это же forward iterator, он "+" и не должен понимать, вроде как.
std::advance работает?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[15]: cstring_iterator
От: ioni Россия  
Дата: 14.07.11 10:33
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, ioni, Вы писали:


I>>
I>>    сstring_iterator s = cstring_iterator(str) + 1; //не собираается
I>>


J>и не должно — это же forward iterator, он "+" и не должен понимать, вроде как.

J>std::advance работает?

это компилируется
std::advance( cstring_iterator(str), 1 );
Re[15]: cstring_iterator
От: ioni Россия  
Дата: 14.07.11 10:46
Оценка: 3 (1) :))
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, ioni, Вы писали:


I>>
I>>    сstring_iterator s = cstring_iterator(str) + 1; //не собираается
I>>


J>и не должно — это же forward iterator, он "+" и не должен понимать, вроде как.

вы правы если поменять forward на random_access то вообще все падает
Re[10]: cstring_iterator
От: igna Россия  
Дата: 14.07.11 14:48
Оценка:
Здравствуйте, ioni, Вы писали:

I>вот так postincrement не вылетает


I>        if( tmp.str_ ) operator++();


Эту проверка опять же лишняя in release mode, поскольку если _str == 0, то итератор сингулярный, а сингулярный итератор инкрементировать нельзя.
Re[13]: cstring_iterator
От: igna Россия  
Дата: 14.07.11 17:10
Оценка: 1 (1)
Здравствуйте, Alexander G, Вы писали:

AG>Всё собирается. Исправил ошибку, вот:


AG>http://codepad.org/7HVj94bg


Там очевидно тоже копируется '\0' в случае пустой строки.
Re[14]: cstring_iterator
От: Alexander G Украина  
Дата: 14.07.11 21:32
Оценка: 1 (1)
Здравствуйте, igna, Вы писали:

I>Там очевидно тоже копируется '\0' в случае пустой строки.


А, ну да. Может переопределить не increment, а equal, как я ранее предложил:


class cstring_iterator
    : public boost::iterator_adaptor<
        cstring_iterator,
        char const *,
        boost::use_default,
        boost::forward_traversal_tag>
{
public:
    explicit cstring_iterator(char const * buffer = 0)
        : iterator_adaptor_(buffer)
    {
    }
 
    bool equal(cstring_iterator const & other) const
    {
        if ( other.base() == NULL )
        {
           return ( *this->base() == '\0' );
        }
        else if ( this->base() == NULL )
        {
           return ( *other.base() == '\0' );
        }
        else
        {
           return ( other.base() == this->base() );
        }
    }
 
    friend class boost::iterator_core_access;
};
Русский военный корабль идёт ко дну!
Re[15]: cstring_iterator
От: igna Россия  
Дата: 15.07.11 05:56
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>А, ну да. Может переопределить не increment, а equal, как я ранее предложил:


AG>    bool equal(cstring_iterator const & other) const
AG>    {
AG>        if ( other.base() == NULL )
AG>        {
AG>           return ( *this->base() == '\0' );
AG>        }
AG>        else if ( this->base() == NULL )
AG>        {
AG>           return ( *other.base() == '\0' );
AG>        }
AG>        else
AG>        {
AG>           return ( other.base() == this->base() );
AG>        }
AG>    }


Логически это именно то, что надо, но может оказаться неоптимальным в некоторых случаях; например, если сравниваются два несингулярных итератора. Если достаточен forward iterator, лучше все же обнулять указатель сразу как только он устанавливается на конец строки. (Мест таких два: в конструкторе и в операторе инкрементирования, поэтому проверку и обнуление имеет смысл вынести в отдельную функцию.)

А вот если нужен random access iterator, то может быть и так, как ты предложил, хотя я бы подумал еще, не лучше ли сохранять указатель на последний символ/знак строки перед обнулением указателя, чтобы оператор декрементирования мог восстановить его. Правда тогда в итераторе потребуется еще одно поле.

В любом случае библиотека общего назначения должна бы иметь оба эти итератора для строки заканчивающейся нулем: один как forward iterator, второй как random access iterator.
Re[16]: cstring_iterator
От: Alexander G Украина  
Дата: 15.07.11 06:55
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, Alexander G, Вы писали:


AG>>А, ну да. Может переопределить не increment, а equal, как я ранее предложил:


I>
AG>>    bool equal(cstring_iterator const & other) const
AG>>    {
AG>>        if ( other.base() == NULL )
AG>>        {
AG>>           return ( *this->base() == '\0' );
AG>>        }
AG>>        else if ( this->base() == NULL )
AG>>        {
AG>>           return ( *other.base() == '\0' );
AG>>        }
AG>>        else
AG>>        {
AG>>           return ( other.base() == this->base() );
AG>>        }
AG>>    }
I>


I>Логически это именно то, что надо, но может оказаться неоптимальным в некоторых случаях; например, если сравниваются два несингулярных итератора.


Я думаю, цикл с диапазоном из двух несингулярных итераторов в случае такого equal оптимальнее.
В случае проверки в increment будет разыменование. В случае проверки в equal выполнится последняя ветка, которая ничего не разыменует.

I>А вот если нужен random access iterator, то может быть и так, как ты предложил, хотя я бы подумал еще, не лучше ли сохранять указатель на последний символ/знак строки перед обнулением указателя, чтобы оператор декрементирования мог восстановить его. Правда тогда в итераторе потребуется еще одно поле.


Хорошего random access iterator из этой идеи не получится. Для random access iterator требуется операция distance, она будет за линейное время при наличии сингулярного итератора. Даже хорошего bidirectional не получится — past-the-end должен быть декрементируемым, это не сработает для cstring_iterator, изначально сконструированного сингулярным.

I>В любом случае библиотека общего назначения должна бы иметь оба эти итератора для строки заканчивающейся нулем: один как forward iterator, второй как random access iterator.


Должна библиотека общего назначения включать такие микрооптимизации?
Русский военный корабль идёт ко дну!
Re[17]: cstring_iterator
От: igna Россия  
Дата: 15.07.11 08:58
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>В случае проверки в increment будет разыменование.


В типичном случае это разыменование будет соптимизировано, поскольку где-то неподалеку будет находиться еще одно разыменование от оператора разыменования. А вот сравнение с нулем в типичном случае сравнения несингулярных итераторов соптимизировать будет нельзя.

AG>Хорошего random access iterator из этой идеи не получится. Для random access iterator требуется операция distance, она будет за линейное время при наличии сингулярного итератора.


Это не так, ты же знаешь, что символы строки хранятся непрерывно, значит смело можешь вычитать. Даже проверка на 0 in release mode не нужна, поскольку сингулярный итератор в качестве аргумента distance использовать нельзя.
Re[18]: cstring_iterator
От: Alexander G Украина  
Дата: 15.07.11 11:16
Оценка: 9 (1)
Здравствуйте, igna, Вы писали:

I>В типичном случае это разыменование будет соптимизировано, поскольку где-то неподалеку будет находиться еще одно разыменование от оператора разыменования. А вот сравнение с нулем в типичном случае сравнения несингулярных итераторов соптимизировать будет нельзя.


Если считать сравнения, то сравнение с нулём всё равно будет, в данном случае с нулевым символом. Нужно смотреть результат компиляции, чтобы сказать точно, что быдет лучше.


AG>>Хорошего random access iterator из этой идеи не получится. Для random access iterator требуется операция distance, она будет за линейное время при наличии сингулярного итератора.


I>Это не так, ты же знаешь, что символы строки хранятся непрерывно, значит смело можешь вычитать. Даже проверка на 0 in release mode не нужна, поскольку сингулярный итератор в качестве аргумента distance использовать нельзя.


http://codepad.org/7zE1H2e8
Русский военный корабль идёт ко дну!
Re[19]: Результат компиляции
От: igna Россия  
Дата: 15.07.11 16:15
Оценка: 1 (1)
Здравствуйте, Alexander G, Вы писали:

AG>Если считать сравнения, то сравнение с нулём всё равно будет, в данном случае с нулевым символом. Нужно смотреть результат компиляции, чтобы сказать точно, что быдет лучше.


Смотрим результат компиляции:

increment
$LL45@main:
    movsx    ecx, cl
    inc    edx
    add    eax, ecx
    mov    cl, BYTE PTR [edx]
    test    cl, cl
    jne    SHORT $LL45@main


equal
$LL41@main:
    mov    cl, BYTE PTR [edx]
    test    cl, cl
    sete    bl
    test    bl, bl
    jne    SHORT $LN76@main
    movsx    ecx, cl
    add    eax, ecx
    inc    edx
    jmp    SHORT $LL41@main
$LN76@main:
Re[20]: Результат компиляции
От: Alexander G Украина  
Дата: 15.07.11 17:49
Оценка:
Здравствуйте, igna, Вы писали:

AG>>Если считать сравнения, то сравнение с нулём всё равно будет, в данном случае с нулевым символом. Нужно смотреть результат компиляции, чтобы сказать точно, что быдет лучше.


I>Смотрим результат компиляции:


Вот теперь вижу, хотя физический смысл использования регистра bl неясен
Русский военный корабль идёт ко дну!
Re[21]: Результат компиляции
От: igna Россия  
Дата: 16.07.11 05:05
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Вот теперь вижу, хотя физический смысл использования регистра bl неясен


Возможно, что компилятор выполнил столько оптимизаций, что на последнюю его не хватило.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.