Boost logo

Boost :

From: Thorsten Ottosen (nesotto_at_[hidden])
Date: 2003-10-27 08:33:54


"Pavol Droba" <droba_at_[hidden]> wrote in message
news:20031026155020.GG17011_at_lenin.felcer.sk...
> On Mon, Oct 27, 2003 at 02:07:47AM +1100, Thorsten Ottosen wrote:

> > You also called your functions firnd_first, not find_0th, and we have
> >
> > find_first( s, XX ) == find_nth( s, XX, 0 )
> >
> > which doesn't seem natural. It's like having an integer variable and
making
> > zero mean you have got one
> > of something.
> >
>
> What would then denote find_nth( s, XX, 0 )? Should it throw an exception?

a good idea. the argument could be an int and you could prevent [-max_int,0]
as input.
There's been some heated discussion once in a while, but I still don't get
that one would like to
use unsigned types.

> Why would you use
>
> for( unsigned int i=1; i<=n; i++ )
> {
> // do something with
> find_nth( s, XX, i );
> }
>
>
> and
>
> for( unsigned int i=0; i<n; i++ )
> {
> vector[i] = i;
> }
>
> ?

I don't see the similarity between the two examples. One is *searching* for
substrings another
is merely *accessing* a random access container at index i. It's not obvious
at all that these have anything in common;
So I merely asking for a good explanation :-)

>
> It is one of most basic conventions in C programing, that first element
has
> the index 0.
> Whatever are your reasons, but you want want to break something very
fundamental.

I don't know. It's like making the 1st of december into the 0th of december
AFAICT. I don't suppose date libraries do that.

> I'm against anything which would imply some explicit affinity to
std::string.
>
> I'm not against improvements to the iterator_range, but only with a
respect
> to an arbitrary container.
>
> We can call it substring, but only in terms of the string definition, I
have already
> mentioned. Everything else is a hack.
>
> So you most probably will not convince me to prefer std::basic_string in
the context
> of this library. It would break the basic properties of the design.

here'a a small hack. Maybe it's useful? Anyway, it shows how a substring
might be useful. The implementation could be better too.
If a "string" concept required a sequential data, the substring class could
probably be implemented in terms of char*.

#include <boost/string_algo.hpp>
#include <string>
#include <iosfwd>
#include <iterator>
#include <cstddef>

using namespace boost;

template< typename String >
class basic_substring
{
 typedef typename string_algo::container_result_iterator<String>::type
iterator;
 typedef typename string_algo::container_value_type<String>::type
value_type;
 iterator begin_;
 iterator end_;

public:
 basic_substring( iterator b, iterator e )
 : begin_( b ), end_( e )
 {}

 iterator begin() const
 {
  return begin_;
 }

 iterator end() const
 {
  return end_;
 }

 std::size_t size() const
 {
  return std::distance( begin_, end_ );
 }

 bool empty() const
 {
  return begin_ == end_;
 }

    typedef iterator (basic_substring::* safe_bool)();
 operator safe_bool() const
 {
  return empty() ? 0 : &end;
 }

    friend inline std::ostream& operator<<( std::ostream& out,
                                         basic_substring& s )
 {
  iterator i = s.begin_;
  while( i != s.end_ )
  {
   out << *i;
   ++i;
  }
  return out;
 }
};

template< typename String1, typename String2 >
std::basic_string< typename string_algo::container_value_type<String1>::type
>
operator+( const basic_substring<String1>& lhs, const
basic_substring<String2>& rhs )
{
    std::basic_string< typename
string_algo::container_value_type<String1>::type > s( lhs.begin(),
lhs.end() );
    s.insert( s.end(), rhs.begin(), rhs.end() );
    return s;
}

template< typename String >
std::basic_string< typename string_algo::container_value_type<String>::type
>
operator+( const basic_substring<String>& lhs, const
std::basic_string<typename string_algo::container_value_type<String>::type>&
rhs )
{
    std::basic_string< typename
string_algo::container_value_type<String>::type > s( lhs.begin(),
lhs.end() );
    s.insert( s.end(), rhs.begin(), rhs.end() );
    return s;
}

template< typename String >
std::basic_string< typename string_algo::container_value_type<String>::type
>
operator+( const std::basic_string<typename
string_algo::container_value_type<String>::type>& lhs, const
basic_substring<String>& rhs )
{
    std::basic_string< typename
string_algo::container_value_type<String>::type > s( lhs.begin(),
lhs.end() );
    s.insert( s.end(), rhs.begin(), rhs.end() );
    return s;
}

typedef basic_substring< std::string > substring;
typedef basic_substring< std::wstring > wsubstring;
typedef basic_substring< const std::string > const_substring;
typedef basic_substring< const std::wstring > const_wsubstring;

template< typename String, typename SearchString >
basic_substring<String> find( String& s, const SearchString& bla )
{
    return basic_substring<String>( string_algo::begin( s ),
string_algo::end( s ) );
}

template< typename SearchString >
basic_substring<std::string> find( char* s, const SearchString& bla )
{
    return basic_substring<std::string>( string_algo::begin( s ),
string_algo::end( s ) );
}

#include <iostream>

int main()
{
    using namespace std;
    char array[] = "array hello";
 string s = "hello world";
 const string cs = "Hello World!";
 substring match = find( s, "blabla" );
    const_substring match2 = find( cs, "blafoo" );
    substring match3 = find( array, "foobar" );
 cout << match << match2 << match3;

    cout << "fooo" + match + match2 + find( s, "goo" );

}

> And btw, you are right the in multi-threaded multi-locales environment,
> global locales are absolutely unusable ...

yeah, that must be the best argument.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk