Subject: Re: [boost] [range] strings
From: Mathias Gaunard (mathias.gaunard_at_[hidden])
Date: 2010-03-08 07:57:33


Domagoj Saric wrote:
> Currently, the following assertion:
> char const test_string[] = "a test string";
> assert( test_string == boost::as_literal( test_string ) );
> fails
> while the following one:
> assert( test_string == boost::as_literal( test_string ).advance_end( 1 ) );
> passes because the left-hand side parameter of operator== is implicitly
> converted to a boost::iterator_range<> object which _includes_ the trailing zero
> (because it is treated as any other array) while the boost::iterator_range<>
> returned by boost::as_literal<>() _excludes_ the trailing zero...
>
> I 'know' that there is no 'happy' solution for this because the status quo is
> 'consistent' across all types but it, on the other hand, creates problems (or
> unexpected results)

I personally do not find that unexpected. An array of size N is a range
of its N elements.

> like the one outlined above, when strings, char pointers
> and literals are used...For this reason I would prefer more the other 'less than
> happy' solution that would treat strings in a special way (by never including
> the trailing zero)...

I believe this used to be the default, but was changed.

Also, consider char arrays that have zeros in the middle on purpose,
and/or that are not strings.

> Another problem is that the conversion, implict or otherwise

AFAIK there is actually no conversion going on. It just calls
template<typename Range>
bool operator==(Range&, const iterator_range<const char*>&);

> from a char
> container/range whose iterators are not plain char pointers (e.g. std::strings
> in 'secure STL' implementations) does not work (does not compile). My last post
> in the [program_options] thread offers a 'fix'.

as_literal is not meant to be used on anything else but char (or wide
chars) arrays.

> Yet another problem is that the as_literal<>() template function does not use
> the fact that it was passed an array to implicitly/directly deduce the length
> but it still calls std::strlen().

Indeed, but that's the expected and documented behaviour.

> Additionaly the above mentioned implementations of make_range() and str_end()
> add two extra instructions (substraction and addition) because they use strlen()
> that works with 'indexes'/size which then have to be converted to pointers...

I suspect that strlen on a literal is not really a performance concern.
Nevertheless an adaptor to simply remove the last element of the array
range might be useful indeed.