<functional> header usage

  • Follow


I have used <functional> header rarely so I'm not comfortable with it.
I have written a function

   template <class Pred>
   advance_while(const string& s, int& idx, Pred pred);

that advances idx until pred(s[idx]) is false or idx >= s.size(),
whichever comes first. Naturaly, I want to use it with a few
predicates, each of them identifying a family of characters.

One specific problem is that I want to say "advance while idx is not
whitespace and is not equal to '='". I have a unary_function<char,
bool> for detecting whitespace and I've tried to write:

   advance_while(s, idx,
     logical_and(not1(IsWs()), not1(binder2nd(equal_to<char>(), '='))))

This doesn't work. What is the correct way?

Sure, I know it's easy to do it with an inplace while but my goal here
is to get familiar with the <functional> header.

In case it still isn't clear what I want to do, here is an OCaml
version:

(* The equivalent of these three lines is inside <functional> *)
let compose_pred f pa pb = fun x -> f (pa x) (pb x);;
let logical_and = compose_pred ( && );;
let ( @ ) f g = fun x -> f (g x);; (* compose functions *)

(* This corresponds to the user written code in C++ *)
advance_while s idx (compose_pred (not @ is_ws) (not @ (( = ) '=')));;

regards,
  radu

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply radugrigore 9/3/2004 11:08:07 AM

radugrigore@gmail.com (Radu Grigore) writes:

> I have used <functional> header rarely so I'm not comfortable with it.
> I have written a function
>
>    template <class Pred>
>    advance_while(const string& s, int& idx, Pred pred);
>
> that advances idx until pred(s[idx]) is false or idx >= s.size(),
> whichever comes first. Naturaly, I want to use it with a few
> predicates, each of them identifying a family of characters.
>
> One specific problem is that I want to say "advance while idx is not
> whitespace and is not equal to '='". I have a unary_function<char,
> bool> for detecting whitespace and I've tried to write:
>
>    advance_while(s, idx,
>      logical_and(not1(IsWs()), not1(binder2nd(equal_to<char>(), '='))))
                                      ^^^^^^^^^

I think that should just be bind2nd.  Or you could use Boost.Lambda
and write:

    advance_while(s, idx, !bind(IsWs(), _1) && _1 != '=')

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply David 9/4/2004 1:51:50 AM


Radu Grigore wrote:
> I have used <functional> header rarely so I'm not comfortable with it.
> I have written a function
> 
>    template <class Pred>
>    advance_while(const string& s, int& idx, Pred pred);
> 
> that advances idx until pred(s[idx]) is false or idx >= s.size(),
> whichever comes first. Naturaly, I want to use it with a few
> predicates, each of them identifying a family of characters.

You might like to know that
   advance_while(s, idx, pred);
is equivalent to
   idx = std::find_if(s.begin() + idx, s.end(), pred) - s.begin();

> One specific problem is that I want to say "advance while idx is not
> whitespace and is not equal to '='".

You can use std::string::find_first_of to do that.

> I have a unary_function<char,
> bool> for detecting whitespace and I've tried to write:
> 
>    advance_while(s, idx,
>      logical_and(not1(IsWs()), not1(binder2nd(equal_to<char>(), '='))))
> 
> This doesn't work. What is the correct way?
<snip>

Unlike not1, logical_and isn't designed to be composed with other
functors.  You could write your own functor template that composes
other functors.  It might be worth investigating Boost's Lambda
library <http://www.boost.org/libs/lambda> as an alternative.

-- 
Ben Hutchings
Kids!  Bringing about Armageddon can be dangerous.  Do not attempt it in
your own home. - Terry Pratchett and Neil Gaiman, `Good Omens'

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Ben 9/4/2004 2:15:02 AM

Radu Grigore <radugrigore@gmail.com> wrote:

> I have used <functional> header rarely so I'm not comfortable with it.
> I have written a function
>
>    template <class Pred>
>    advance_while(const string& s, int& idx, Pred pred);
>
> that advances idx until pred(s[idx]) is false or idx >= s.size(),
> whichever comes first. Naturaly, I want to use it with a few
> predicates, each of them identifying a family of characters.

Your function is very similar to std::find_if template, the difference  
being that the latter one uses iterators.

> One specific problem is that I want to say "advance while idx is not
> whitespace and is not equal to '='". I have a unary_function<char,
> bool> for detecting whitespace and I've tried to write:
>
>    advance_while(s, idx,
>      logical_and(not1(IsWs()), not1(binder2nd(equal_to<char>(), '='))))
>
> This doesn't work. What is the correct way?

logical_and<> is a functor that takes not two other functors, rather  
values and return the result of applying operator&& to the values. So, you  
need some tools that will let you feed logical_and<> with functors.

One of this tools is blessed boost::bind (namespace boost omitted):

     advance_while(
           s
         , idx
         , bind(logical_and<bool>(), bind(IsWs(), _1),  
not1(bind(equal_to<char>(), _1, '='))
         );

Using boost::lambda you can make it even much more clear (namespace  
boost::lambda omitted)

     advance_while(
           s
         , idx
         , bind(IsWs(), _1) && (_1 != '=')
         );

(I did not compile it, so errors are mine)

-- 
Maxim Yegorushkin

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Maxim 9/4/2004 2:16:57 AM

Ben Hutchings <ben-public-nospam@decadentplace.org.uk> wrote in message
news:<slrncjh3r6.83h.ben-public-nospam@shadbolt.i.decadentplace.org.uk>...
> Radu Grigore wrote:

>> One specific problem is that I want to say "advance while idx is not
>> whitespace and is not equal to '='".

> You can use std::string::find_first_of to do that.

Only if you can create a string with all of the white spaces in it.  For
std::string, I've occasionally done just that, using something along the
lines of:

     for ( int i = 0 ; i <= UCHAR_MAX ; ++ i ) {
         if ( isspace( i ) ) {
             s += (char)i ;
         }
     }

It's not really portable in the strictest sense, however -- I wouldn't
want to use it on a machine with 32 bit char's, for example:-).

Note to that the results reflect the state of the global locale at the
moment the list is constructed; any later changes in the locale will not
be taken into account.

--
James Kanze           GABI Software         http://www.gabi-soft.fr
Conseils en informatique orient=E9e objet/
                    Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/8/2004 10:44:14 AM

4 Replies
129 Views

(page loaded in 0.079 seconds)


Reply: