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)
|