Ordinary unary function to STL adaptable unary predicate how?

S

SpOiLeR

I have function

bool IsGood (const std::string& sr);

I want to use that function in std::not1 STL functor. I tried this:

not1(IsGood)
/*
error : 'std::unary_negate<_Fn1> std::not1(const _Fn1 &)' : could not
deduce template argument for 'overloaded function type' from 'overloaded
function type'

error: 'std::unary_negate<_Fn1> std::not1(const _Fn1 &)' : could not deduce
template argument for 'overloaded function type' from 'overloaded function
type'
*/

and this

not1(ptr_fun(IsGood))
/*
functional(209): warning : qualifier applied to reference type; ignored
functional(209): error : '_Left' : reference to reference is illegal
*/

both don't work and I don't understand why. Please help.

TIA
 
G

Greg

SpOiLeR said:
I have function

bool IsGood (const std::string& sr);

I want to use that function in std::not1 STL functor. I tried this:

not1(IsGood)
/*
error : 'std::unary_negate<_Fn1> std::not1(const _Fn1 &)' : could not
deduce template argument for 'overloaded function type' from 'overloaded
function type'

error: 'std::unary_negate<_Fn1> std::not1(const _Fn1 &)' : could not deduce
template argument for 'overloaded function type' from 'overloaded function
type'
*/

and this

not1(ptr_fun(IsGood))
/*
functional(209): warning : qualifier applied to reference type; ignored
functional(209): error : '_Left' : reference to reference is illegal
*/

both don't work and I don't understand why. Please help.

TIA

Well, it looks like you may have overloaded the IsGood function and the
compiler cannot figure out which one you mean. Try:

ptr_fun(bool (*IsGood)(const std::string&));

also, not1 may need some assistance with the return type:

std::not1<bool>(ptr_fun(bool (*IsGood)(const std::string&));

There's not really enough code posted though to know for sure what the
exact problem is though.

Greg
 
S

SpOiLeR

Well, it looks like you may have overloaded the IsGood function and the
compiler cannot figure out which one you mean. Try:

ptr_fun(bool (*IsGood)(const std::string&));

also, not1 may need some assistance with the return type:

std::not1<bool>(ptr_fun(bool (*IsGood)(const std::string&));

There's not really enough code posted though to know for sure what the
exact problem is though.

Greg

Well here is some more code. I put this in empty project so there is
nothing more in it than this and still same error occurs. Also, none of
your propositions works:

#include <string>
#include <list>
#include <algorithm>
#include <iostream>

using namespace std;

typedef list<string> ls;

bool IsGood (const string& st) {
return st.empty(); // For sake of demonstration
}

int main ()
{
ls tbl;

tbl.push_back("tgklhdfjh");
tbl.push_back("");
tbl.push_back("");
tbl.push_back("");
tbl.push_back("");
tbl.push_back("");
tbl.push_back("gkjdhgdkfjgh");

ls::iterator lbeg, lend, new_end;
lbeg = tbl.begin();
lend = tbl.end();

// Next one is problematic
new_end = remove_if(lbeg, lend, not1(ptr_fun(IsGood)));
// Compiler gives following:
// functional(209): warning : qualifier applied to reference type; ignored
// functional(209): error C2529: '_Left' : reference to reference is
// illegal

return 1;
}

I just can't figure out what I'm doing wrong...
 
S

SpOiLeR

I have function

bool IsGood (const std::string& sr);

I want to use that function in std::not1 STL functor. I tried this:

not1(IsGood)
OK, this on doesn't work because not1 expects something inherited from
unary_function.
not1(ptr_fun(IsGood))
/*
functional(209): warning : qualifier applied to reference type; ignored
functional(209): error : '_Left' : reference to reference is illegal
*/

I have figured out part of the problem.

If I have

bool IsGood (const std::string& sr);

I am allowed to construct this kind of unary_function

pointer_to_unary_function<const string&,bool> functor_is_good (IsGood);

If I test functor_is_good like this:

bool b_tmp;
string s_tmp;
b_tmp = functor_is_good (s_tmp);

b_tmp has expected result, and no warnings are issued.

But, if I try to use functor_is_good in not1 like this:

not1(functor_is_good)

then errors arise. The problem is that when template for unary_negate is
instantied, somewhere occurs && (reference to reference) argument of some
member function (actually when instantiated const const string& &
occurs), and that is reported as error. Now, if I change

bool IsGood (const std::string& sr);
into
bool IsGood (const std::string sr);

and
pointer_to_unary_function<const string&,bool> functor_is_good (IsGood);
into
pointer_to_unary_function<const string,bool> functor_is_good2 (IsGood);

then expression

not(functor_is_good2) becomes valid and all works fine and as expected.

Is it possible that this is standardized behavior? I mean, STL functors and
adapters that can't adapt functions that use pass by reference seem a bit
strange to me. Could it be a bug in my compiler's STL implementation? I
didn't find in any part of docs that arguments of adapted functions can't
be reference: everywhere I looked it states they can be of arbitrary type.
I'm dazzled and confused... Anybody?
 
A

AnonMail2005

I learned this stuff from Meyers, Effective STL.

Chapter 6 has five short items that deal with Functors,
Functor Classes, Functions, etc.

Some of it is very esoteric (to me) but he shows how to make
functor classes adaptable (derived them from unary_function
or binary_function) and discusses the hows of arg types
when implementing these (strip const and reference off of the
function arg). He also refers to some documents
for those interested in the whys of the way things are done.

Here is a sample:

class IsGood : public std::unary_function<std::string, bool>
public:
bool operator()(const std::string& s) const { // stuff goes here }
};
 
S

SpOiLeR

I learned this stuff from Meyers, Effective STL.

I'll have to check the book, although I don't have it right now.
Chapter 6 has five short items that deal with Functors,
Functor Classes, Functions, etc.

Some of it is very esoteric (to me) but he shows how to make
functor classes adaptable (derived them from unary_function
or binary_function) and discusses the hows of arg types
when implementing these (strip const and reference off of the
function arg).

Does he strictly say that const and references from function arg(s) have to
be stripped off? That would induce that it is standardized behavior.
He also refers to some documents
for those interested in the whys of the way things are done.

Would you be so kind to enumerate some of those docs?
Here is a sample:

class IsGood : public std::unary_function<std::string, bool>
public:
bool operator()(const std::string& s) const { // stuff goes here }
};

Well, I know how to create my own adaptable functor. What I was asking is a
way to create one directly from given ordinary function using existing STL
adaptors. In the case of

bool IsGood (const std::string&);

this proved to be only partially possible and that's what confuses me. Is
it normal that it is not possible to do it, or it is a problem of my
compiler's STL implementation?

Thanks.
 
J

Jeff Flinn

....
Well, I know how to create my own adaptable functor. What I was asking is
a
way to create one directly from given ordinary function using existing STL
adaptors. In the case of

bool IsGood (const std::string&);

this proved to be only partially possible and that's what confuses me. Is
it normal that it is not possible to do it, or it is a problem of my
compiler's STL implementation?

Why not save yourself all of this trouble and use boost.bind library from
www.boost.org.

new_end = remove_if( lbeg, lend, !boost::bind( &IsGood, _1 ) );

which lets you use either your original global function, or the above
funtion object (w/out need to derive from std::unary_function). Although the
former will most likely disallow inlining. bind is now part of TR1, though
without the support for the "!".

Jeff Flinn
 
S

SpOiLeR

Why not save yourself all of this trouble and use boost.bind library from
www.boost.org.

new_end = remove_if( lbeg, lend, !boost::bind( &IsGood, _1 ) );

which lets you use either your original global function, or the above
funtion object (w/out need to derive from std::unary_function). Although the
former will most likely disallow inlining. bind is now part of TR1, though
without the support for the "!".

Jeff Flinn

boost has done me good many times before so you're probably right (Saying
probably because I haven't used this part of boost yet :). I'll check the
docs and see how things will work...

Anyway, I have found some interesting reading about these problems here:

http://www.progdoc.de/papers/adapter_binder/adapter_binder/adapter_binder.html

If someone is interested...
 
J

Jeff Flinn

SpOiLeR said:
boost has done me good many times before so you're probably right (Saying
probably because I haven't used this part of boost yet :). I'll check the
docs and see how things will work...

Anyway, I have found some interesting reading about these problems here:

http://www.progdoc.de/papers/adapter_binder/adapter_binder/adapter_binder.html

I haven't read the article, but I think these problems were the original
impetus for the boost.functional library replacements for not1, ...

Jeff
 
S

SpOiLeR

I haven't read the article, but I think these problems were the original
impetus for the boost.functional library replacements for not1, ...

Jeff

Yep, I'd say they were.

Anyway, boost::bind works perfectly. Is is so good, that I was able to
remove 5 (!) single-time-used functor classes. All that didn't make my code
garbled, but I would say just the opposite. Strange that I haven't
remembered before to check if boost has something in store for me (till now
I used smart_ptr, string_algo and regex). I guess man can never say enough
about how useful this lib collection can be. Thanks for the idea.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top