Boost logo

Boost Users :

Subject: Re: [Boost-users] Range - Char literal question
From: Neil Groves (neil_at_[hidden])
Date: 2010-10-19 19:31:11


On Mon, Oct 18, 2010 at 9:24 PM, Rao, Anant <Anant.Rao_at_[hidden]>wrote:

>
>
> Hi,
>
>
>
> I need to iterate thru strings (For various reasons, I can’t use string or
> vector<char> containers).
>
> I found that boost::range exactly fits the bill for me. I get all the
> convenience of an iterator (from as_literal.hpp).
>
>
>
> I have a piece of code
>
>
>
> char* char_s = "I am fine";
>
> char *cp;
>
>
>
> std::size_t sz = strlen(char_s);
>
> const char* str_end1 = str_begin( char_s ) + sz;
>
>
>
> for (cp = str_begin(char_s); cp != str_end(char_s); ++cp)
>
> cout << *cp;
>
>
>
> I have couple of questions:
>
>
>
> 1. In the loop, boost::range seems to be calling strlen every
> iteration. This is an overhead. I was wondering if there’s a way I can pass
> in the length myself so that boost::range would use it and avoid calling
> strlen().
>
> Indeed in the code snippet provided it would be called every iteration.
Since you could simply store the end and compare of course.

However the issue is a little artifical because you would normally have an
algorithm which you which to apply to a range. In your example, your
algorithm is simply to stream each character. This can be achieved by a
number of different approaches.

The most direct standard approach is:
std::cout << char_s;

The most direct range-based approach available in boost 1.43 and greater is:

#include <ostream>
#include <boost/range.hpp>
#include <boost/range/algorithm/copy.hpp>
...
boost::copy( boost::as_literal(char_s),
std::ostream_iterator<char>(std::cout) );

This example better demonstrates the reason why the re-evaluation of strlen
does not occur in practice. The as_literal function evaluates strlen once to
obtain the end iterator. The first and last iterators are stored in a range
which is then passed into another algorithm, in this case boost::copy. When
the boost::range is queried for the end it is a constant-time operation,
hence strlen is not re-evaluated.

2. If it’s not possible, is there a way for me to use iterators (boost
> or non-boost) over char strings?
>
>
It is possible to use iterators over char strings. This does not require
Boost.Range or even Boost. The C++ standard carefully designed iterators
such that pointers are models of the Random Access Iterator Concept. Hence
you can do this:

#include <algorithm>
#include <iostream>

const char* char_s = "abcd";
std::copy( char_s, char_s + strlen(char_s),
std::ostream_iterator<int>(std::cout) );

> Thanks so much in advance for your help,
>
> Anant
>
> I hope this answers your question satisfactorily. Are you avoiding string
and vector<char> to eliminate heap operations for small strings? Decent
implementations of string with the small buffer optimization are fast enough
for almost all purposes. Otherwise it might be worth implementing or using a
fixed string. I would like to stress though that the final container type of
a Boost.Range idiomatic design would be unimportant to the algorithm. The
algorithm would merely deal in models of the Range Concepts, please see
http://www.boost.org/doc/libs/1_44_0/libs/range/doc/html/range/concepts.html.

The power of this separation is exemplified by your example. If you decide
to implement a new fixed string class you would still be able to utilise the
string algorithms within Boost.Algorithm despite these never having been
designed for use with your new class.

Best wishes,
Neil Groves



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net