473,406 Members | 2,259 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

How do I negate a find_if condition properly?

I have a vector of TCard objects, I am sorting them based on the the
box field. That part works fine (finally!). I would then like to
random_shuffle all cards that are in a particular box, that is, I would
find the first card that is in box 3, then the first one after that
which isn't in box 3, and random_shuffle that range instead of the
usual begin(), end(). For the "not in box 3," I kept trying to use the
not1 function but I couldn't get anything that would compile. So I
ended up with (attempt #11):

class FindIfBox
{
public:
FindIfBox(int box): m_box(box) {}
int GetBox() { return m_box; }
bool operator() (const TCard& card) const
private:
int m_box;
};
//...
bool FindIfBox::operator() (const TCard& card) const
{
// will have to be rewritten for Box 0
if (this->m_box >= 0)
return card.m_box == this->m_box;
else
return !(card.m_box == this->m_box);
}
//...
vector<TCard>::iterator boxBegin, boxEnd;

// the sort works perfectly
// not showing InLesserBox function object
stable_sort(v.begin(), v.end(), InLesserBox());

boxBegin = find_if(v.begin(), v.end(), FindIfBox(3));
boxEnd = find_if(boxBegin, v.end(), FindIfBox(-3));

//... (print vector)
// try to shuffle cards with that have box = 3
random_shuffle(boxBegin, boxEnd);

//.. (print vector - and it hasn't changed)
// by the way there are some elements after the box 3 that are in box 4

It took me two weeks to get something that would compile. I obviously
have some logic error because the vector doesn't change after the
shuffle. Maybe I have a temporary going out of scope somewhere, that's
what it usually is, right? Or a missing &.

I wanted to be able to say (and this doesn't compile)
boxEnd = find_if(boxBegin, v.end(), not1(FindIfBox(3));

Is there a way to say something like that using valid C++ so I don't
have to junk up my operator() member function in the FindInBox object?

Jul 27 '05 #1
5 2978
dave_if wrote:
class FindIfBox
{
public:
FindIfBox(int box): m_box(box) {}
int GetBox() { return m_box; }
bool operator() (const TCard& card) const
private:
int m_box;
};


According to the requirements for unary functions, this is not a
unary in the sense of STL. Unfortunately, I don't think that the
standard really spells out the requirements for unary functions
explicitly. Essentially, if 'UF' is unary function type, 'uf' is
an object thereof, 'A' is the argument type, 'a' an object thereof,
and 'R' the result type, the following shall be legal;

Expression Type Semantic
UF::argument_type A type of the argument
UF::result_type R type returned by the function call
uf(a) R function call

Effectively, these requirements turn normal functions into useless
function objects if they are indeed imposed. Many algorithms and
uses of function object have relaxed requirements which do not
need the associated types. However, the current function adaptors
normally do have these requirements which is the reason why you
you have to use 'ptr_fun()', 'mem_fun()', etc. if you want to
adapt normal functions.

The following program compiled fine for me and I'm confident that
it does what you want it to do:

#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <algorithm>
struct TCard
{
int m_box;
};

class FindIfBox
{
public:
typedef TCard argument_type;
typedef bool result_type;

FindIfBox(int box): m_box(box) {}
int GetBox() { return m_box; }
bool operator() (const TCard& card) const
{
return this->m_box == card.m_box;
}
private:
int m_box;
};

int main()
{
std::vector<TCard> v;

std::vector<TCard>::iterator boxBegin
= std::find_if(v.begin(), v.end(), FindIfBox(3));
std::vector<TCard>::iterator boxEnd
= std::find_if(boxBegin, v.end(), std::not1(FindIfBox(3)));
}
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Jul 27 '05 #2
Dietmar Kuehl wrote:
[only relevant part quoted]
According to the requirements for unary functions, this is not a
unary in the sense of STL. Unfortunately, I don't think that the
standard really spells out the requirements for unary functions
explicitly. Essentially, if 'UF' is unary function type, 'uf' is
an object thereof, 'A' is the argument type, 'a' an object thereof,
and 'R' the result type, the following shall be legal;

Expression Type Semantic
UF::argument_type A type of the argument
UF::result_type R type returned by the function call
uf(a) R function call

Effectively, these requirements turn normal functions into useless
function objects if they are indeed imposed.


The standard provides a mechanism for dealing with this in <functional>
called std::ptr_fun, which returns an object of type
std::pointer_to_unary_function. So if you have a function, example --

int sqr(int x) { return x*x ; }

-- you could adapt it to meet the requirements of a unary function with
std::ptr_fun(sqr).

-Alan
Jul 27 '05 #3
"dave_if" <da*******@gmail.com> wrote in news:1122437830.358564.54390
@o13g2000cwo.googlegroups.com:
I have a vector of TCard objects, I am sorting them based on the the
box field. That part works fine (finally!). I would then like to
random_shuffle all cards that are in a particular box, that is, I would
find the first card that is in box 3, then the first one after that
which isn't in box 3, and random_shuffle that range instead of the
usual begin(), end(). For the "not in box 3," I kept trying to use the
not1 function but I couldn't get anything that would compile. So I
ended up with (attempt #11):

class FindIfBox
{
public:
FindIfBox(int box): m_box(box) {}
int GetBox() { return m_box; }
bool operator() (const TCard& card) const
private:
int m_box;
}; [snip]
I wanted to be able to say (and this doesn't compile)
boxEnd = find_if(boxBegin, v.end(), not1(FindIfBox(3));

Is there a way to say something like that using valid C++ so I don't
have to junk up my operator() member function in the FindInBox object?


Try deriving FindIfBox from std::unary_function< TCard, bool >, like this:

struct TCard
{
int m_box;
};

struct InLesserBox : public std::binary_function< TCard, TCard, bool >
{
bool operator()(const TCard& card1, const TCard& card2) const
{
return card1.m_box < card2.m_box; // for example
}
};

struct FindIfBox : public std::unary_function< TCard, bool >
{
FindIfBox(int box) : m_box(box) {} // as before
bool operator()(const TCard& card) const
{ return m_box == card.m_box; }
private:
int m_box;
};
int main(int argc, char* argv[])
{
std::vector<TCard> v;
std::vector<TCard>::iterator boxBegin, boxEnd;

// the sort works perfectly
// not showing InLesserBox function object
stable_sort(v.begin(), v.end(), InLesserBox());

boxBegin = find_if(v.begin(), v.end(), FindIfBox(3));
boxEnd = find_if(boxBegin, v.end(), not1(FindIfBox(3)));
// note number of )))
//boxEnd = find_if(boxBegin, v.end(), FindIfBox(-3));

//... (print vector)
// try to shuffle cards with that have box = 3
random_shuffle(boxBegin, boxEnd);

//.. (print vector - and it hasn't changed)
// by the way there are some elements after the box 3 that are in box 4

return 0;
}
Technically, FindIfBox is a binary_function< TCard, int, bool > and you
should use it with bind2nd, but a unary_function with a constructor is
simpler.

// Note: no constructor, no member variable
struct FindIfBox2 : public std::binary_function< TCard, int, bool >
{
bool operator()(const TCard& card, int box) const
{ return box == card.m_box; }
};

boxEnd = find_if( boxBegin, v.end(),
std::not1( std::bind2nd( FindIfBox2(), 3 ) )
);

--
Life is complex, with real and imaginary parts.
Jul 27 '05 #4
Thanks, Dietmar! What a difference those typedefs make! I remember
seeing that in Bjarne's C++PL book but I didn't know those were
actually required. So this is the solution I decided to use, because I
put those 2 typedefs in and fixed the function object and now I can do
what I want.

Csaba, I'll look closely at your code too. I tried to use the bind2nd
function before, but without properly deriving my FindIfBox from
binary_function<>. I remember reading dire warnings from Bjarne saying
to use those unary_function and binary_function templates or else
learn the hard way why they are important, but I couldn't figure out
how to use them, and I couldn't find any sample code other than
Bjarne's that used them.

Thanks Alan for your insights too. At one time I had a FindIfBox
function as part of the TCard class, I never could get the mem_fun or
mem_fun_ref to work either. Probably need to spend a few bucks and get
Josuttis' book, but I'm postponing it as long as I can!

Jul 27 '05 #5
Csaba, in rereading my note to you, I meant to put a "Thanks" there
also!

Jul 27 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
by: mikets | last post by:
Hi there, I found out that very often I use the following construct: for (it = myvec.begin(); it != myvec.end(); ++it) { if (it->name() == "myname") break; } Certainly, the container the...
1
by: John Black | last post by:
Hi, In using find_if() you need to name a comparision function which normally is a static function, but sometimes it is really inconvinient for this, let's take this example, class MyClass{...
3
by: marco_segurini | last post by:
Hi, when the following code is executed bool Test1(); bool Test2(); .... if (Test1() || Test2()) { ... } ....
4
by: Michael | last post by:
Hi, I'm having a few problems getting the following find_if to work class Entity { }; class factory {
18
by: ma740988 | last post by:
Trying to get more acclimated with the use of function objects. As part of my test, consider: # include <vector> # include <iostream> # include <algorithm> #include <stdexcept> #include...
3
by: devel | last post by:
Hello, Could someone tell me why the find_if statement applied to my multimap dictionnary is doesn't compile? Does this algorithm doesn't work on a multimap? I don't understand why the...
1
by: AlanJSmith | last post by:
can some clever guru help please. I am porting some C++ 6.0 projects to C++ VS2005 and find_if no longer exists in vector, i am not sure what to do. i am only at begginer level so please dont get...
10
by: JDT | last post by:
Hi, The following find_if works fine to me except that I want the internal individual comparison performed backward (from m+5, m+4, ..., to m). I can use reverse() to reverse the array first...
10
by: barabenka | last post by:
How can I use find_if with vector of data structures? I have something like this: struct Record{ int ID; int Data1; int Data2; };
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.