STL list Problems


M

Mike Copeland

I'm getting more and more confused about working with STL containers:
everything I try seems to produce a new compiler diagnostic. Here's the
latest (and simplest) thing I've tried to do:

struct TEST
{
int num;
int count;
string str;
bool operator==(const TEST &l, const TEST &r) const
{
return l.num == r.num;
}
} testWork;

The compiler produces "C:\CPP\source\list21.cpp(40) : error C2804:
binary 'operator ==' has too many parameters" -I am totally puzzled
about what this means...and why.
I am _trying_ to create a small structure to be used in an STL list
(e.g. list<TEST>) that I could sort and change values. The first step
(I thought) was to define an operator that would support "find", but I
can't get anything to compile.
I'd appreciate some guidance on how to get going on this task (the
"find", changing object elements, etc.). TIA
 
Ad

Advertisements

Z

ZikO

Mike said:
I'm getting more and more confused about working with STL containers:
everything I try seems to produce a new compiler diagnostic. Here's the
latest (and simplest) thing I've tried to do:

struct TEST
{
int num;
int count;
string str;
bool operator==(const TEST &l, const TEST &r) const
{
return l.num == r.num;
}
} testWork;

The compiler produces "C:\CPP\source\list21.cpp(40) : error C2804:
binary 'operator ==' has too many parameters" -I am totally puzzled
about what this means...and why.
I am _trying_ to create a small structure to be used in an STL list
(e.g. list<TEST>) that I could sort and change values. The first step
(I thought) was to define an operator that would support "find", but I
can't get anything to compile.
I'd appreciate some guidance on how to get going on this task (the
"find", changing object elements, etc.). TIA
There are 2 ways of defining operator==() in global scope (taking 2
parameters) and class scope taking only 1 argument because the first one
is assumed to be the class type. I suspect this is the problem. Try to
get rid of the first parameter and leave only the second one in
definition or you move it outside the class.
 
A

Alf P. Steinbach

* Mike Copeland:
I'm getting more and more confused about working with STL containers:
everything I try seems to produce a new compiler diagnostic. Here's the
latest (and simplest) thing I've tried to do:

struct TEST

Don't use all uppercase names except for idiomatic usage and macros.

For macros do use all uppercase names.

See the various FAQs on the net about this issue.

{
int num;
int count;
string str;
bool operator==(const TEST &l, const TEST &r) const
{
return l.num == r.num;
}
} testWork;

The compiler produces "C:\CPP\source\list21.cpp(40) : error C2804:
binary 'operator ==' has too many parameters" -I am totally puzzled
about what this means...and why.

Consider how to call your operator:

TEST a, b, c;

if( a.operator==( b, c ) ) { ... }

What does the 'a' object have to do with comparing 'b' and 'c', why is the 'a'
object there at all?

But you have specified that there must be some such object, because your
'operator==' is a non-static member routine.

I am _trying_ to create a small structure to be used in an STL list
(e.g. list<TEST>) that I could sort and change values. The first step
(I thought) was to define an operator that would support "find", but I
can't get anything to compile.
I'd appreciate some guidance on how to get going on this task (the
"find", changing object elements, etc.).

Off the cuff,

struct Foo
{
int asd;
int qwe;
};

bool operator<( Foo const& a, Foo const& b )
{
return (a.asd < b.asd) || (a.asd == b.asd && a.qwe < b.qwe);
}

bool operator==( Foo const& a, Foo const& b )
{
return (a.asd == b.asd && a.qwe == b.qwe);
}

Cheers & hth.,

- Alf
 
K

Kai-Uwe Bux

Mike said:
I'm getting more and more confused about working with STL containers:
everything I try seems to produce a new compiler diagnostic. Here's the
latest (and simplest) thing I've tried to do:

struct TEST
{
int num;
int count;
string str;
bool operator==(const TEST &l, const TEST &r) const
{
return l.num == r.num;
}
} testWork;

The compiler produces "C:\CPP\source\list21.cpp(40) : error C2804:
binary 'operator ==' has too many parameters" -I am totally puzzled
about what this means...and why.

Because your operator= has three (sic!) arguments. There are _two_ ways of
declaring and defining operator=. You could use (a) a member function, this
is what you did, or (b) use a free standing function, which could be a
friend if necessary.

Member functions have an implied first argument represented by *this.
Freestanding functions don't. Therefore, a member operator= only has one
parameter and a freestanding operator= has two. Try:

struct Test {
int num;
int count;
string str;
};

bool operator==( Test const & lhs, Test const & rhs ) {
return
( lhs.num == rhs.num )
&& ( lhs.count == rhs.count )
&& ( lhs.str == rhs.str );
}
I am _trying_ to create a small structure to be used in an STL list
(e.g. list<TEST>) that I could sort and change values. The first step
(I thought) was to define an operator that would support "find", but I
can't get anything to compile.

I suggest you don't use operator= unless it really tests for equality. You
can use std::find with any Functor / function: you just have to use find_if
instead.
I'd appreciate some guidance on how to get going on this task (the
"find", changing object elements, etc.). TIA

Without specific questions, the best advice I have to offer is: try a lot
and hit the books. If you have specific questions (like the one above),
answers can be given, and you will likely get an answer here.


Best

Kai-Uwe Bux
 
M

Mike Copeland

struct TEST
There are 2 ways of defining operator==() in global scope (taking 2
parameters) and class scope taking only 1 argument because the first one
is assumed to be the class type. I suspect this is the problem. Try to
get rid of the first parameter and leave only the second one in
definition or you move it outside the class.

Regretfully, I don't know what you're suggesting...or how to do such
a thing. Can you provide an example?
 
M

Mike Copeland

I am _trying_ to create a small structure to be used in an STL list
Here is how I've changed the code, but still I cannot get it to
compile:
#pragma warning (disable:4786)
#include <iostream>
#include <list>
#include <string>
#include <algorithm>

using namespace std;

struct test
{
int key;
int count;
string str;
bool operator==(const test &rhs)
{
return rhs.key == key;
}
} tWork;
list<test> L;
list<test>::iterator qq;

int main(void)
{
char str[100];

for (int ii = 1; ii <= 10; ii++)
{
tWork.count = 0, tWork.key = ii;
sprintf(str, "Test string #%d", ii);
tWork.str = str;
L.push_back(tWork);
} // for
int jj = 5;
qq = find(L.begin(), L.end(), jj); <== error here

return 0;
}

The compiler generates the error (C2679 in VS6.0) stating that I have
no == comparison operator. I thought I did have such an operator (in
the struct definition), but I clearly don't know what I'm doing here 8
<{{
Please advise. TIA
 
Ad

Advertisements

K

Kai-Uwe Bux

Mike said:
Here is how I've changed the code, but still I cannot get it to
compile: ....
list<test> L;
list<test>::iterator qq; ....
int jj = 5;
qq = find(L.begin(), L.end(), jj); <== error here

Note that jj has type int, not type test. The operator== does not (and
should not) compare ints and tests.

[snip]


Best

Kai-Uwe Bux
 
S

SG

   Here is how I've changed the code, but still I cannot get it to
compile:
#pragma warning (disable:4786)

Eew! What's that for? :p
#include <iostream>
#include <list>
#include <string>
#include <algorithm>

using namespace std;

struct test
{
  int    key;
  int    count;
  string str;
  bool operator==(const test &rhs)
  {
      return rhs.key == key;
  }
} tWork;

Stay away from global (namespace scope) variables -- in this case:
tWork.
        list<test> L;
        list<test>::iterator qq;

see above
int main(void)
{
        char   str[100];

        for (int ii = 1; ii <= 10; ii++)
        {
                tWork.count = 0, tWork.key = ii;
                sprintf(str, "Test string #%d", ii);

Avoid the C part of the languange when there are better C++
alternatives. Working with bare naked character arrays is usually
more error-prone than dealing with std::string objects (memory leaks,
heap corruption, buffer overflow, ...)
                tWork.str = str;
                L.push_back(tWork);
        }  // for
        int jj = 5;    
        qq = find(L.begin(), L.end(), jj); <== error here

"jj" is of type "int". You didn't supply an operator== which accepts
an object of type "test" on one side and an object of type "int" on
the other side.
   The compiler generates the error (C2679 in VS6.0) stating that I have
no == comparison operator.

I'm not familiar with the error messages of VS6.0. But g++ would have
told you what kind of operator== function your program lacks.


Cheers!
SG
 
M

Mike Copeland

I am _trying_ to create a small structure to be used in an STL list
Note that jj has type int, not type test. The operator== does not (and
should not) compare ints and tests.

Fair enough, but how do I pass a value (to be compared) of a
structure field to/through a find call? In this situation, I want to
find the list object that has 5 in the field named "key". (All examples
I've found of the STL find algorithm always seem to be for scalar
objects, but I need to have the find "find" an structure object...)
 
M

Mike Copeland

I've found of the STL find algorithm always seem to be for scalar

Sorry, I'm still not getting this. Again, here's my structure:
#pragma warning (disable:4786)
#include <iostream>
#include <list>
#include <string>
#include <algorithm>
using namespace std;
struct test
{
int key;
int count;
string str;
} tWork;
list<test> L;
list<test>::iterator qq;

bool keyMatched(??????????????, ?????????)
{
?????????????
}

int main(void)
{
char str[100];

for (int ii = 1; ii <= 10; ii++)
{
tWork.count = 0, tWork.key = ii;
sprintf(str, "Test string #%d", ii);
tWork.str = str;
L.push_back(tWork);
} // for
int jj = 5;
qq = find_if(L.begin(), L.end(), keyMatched);
// where is "5" passed...and how?

return 0;
}

So, how do I code a comparator routine (e.g. keyMatched) that passes
the currently referenced pointer in the find_if the value which I want
to test for?
 
Ad

Advertisements

S

SG

 Sorry, I'm still not getting this.  Again, here's my structure:

Try something along the lines

struct my_predicate {
int k_;

my_predicate(int k) : k_(k) {}

bool operator()(const test& t)
{
return t.key==k_;
}
};

This way you get an object that "behaves" like a function but in fact
has some state.

You should get a book that covers programming with the STL.
[...]
        int jj = 5;
        qq = find_if(L.begin(), L.end(), keyMatched);  
                        // where is "5" passed...and how?

qq = find_if( L.begin(), L.end(), my_predicate(jj) );


Cheers!
SG
 
Z

ZikO

Mike said:

Sorry, I'm still not getting this. Again, here's my structure:
#pragma warning (disable:4786)
#include <iostream>
#include <list>
#include <string>
#include <algorithm>
using namespace std;
struct test
{
int key;
int count;
string str;
} tWork;
list<test> L;
list<test>::iterator qq;

bool keyMatched(??????????????, ?????????)
{
?????????????
}

int main(void)
{
char str[100];

for (int ii = 1; ii <= 10; ii++)
{
tWork.count = 0, tWork.key = ii;
sprintf(str, "Test string #%d", ii);
tWork.str = str;
L.push_back(tWork);
} // for
int jj = 5;
qq = find_if(L.begin(), L.end(), keyMatched);
// where is "5" passed...and how?

return 0;
}

So, how do I code a comparator routine (e.g. keyMatched) that passes
the currently referenced pointer in the find_if the value which I want
to test for?

STL Algorithms as find_if( ) needs predicate for its functionality. A
predicate is nothing more like another little class with overloaded
operator()() which returns a type which STL Algorithm needs - bool in
your example. Now STL Algorithms take your predicate and by means of
operator()() checks whether it returns true or fault with in similar way
as "if". If the predicate returns true find_if() returns the iterator to
your containers list<test>

Now I think your Predicate should look like (I assume it's true if all
members are equal to the sample !!!! ):

class Predicate {
private:
test value;

public:
bool operator()(const test& obj) {
return (value.key == obj.key)
&& (value.count == obj.count)
&& (value.str == obj.str);
}
};

somewhere in code:

test sample(10,20, "test");
Predicate pred(sample);

qq = find(L.begin(), L.end(), pred);

If it's not working I will try to write for you but not now, sorry. Try
to understand what predicate is and how it works.
 
Z

ZikO

Mike said:
>
> Sorry, I'm still not getting this. Again, here's my structure:
> #pragma warning (disable:4786)
> #include <iostream>
> #include <list>
> #include <string>
> #include <algorithm>
> using namespace std;
> struct test
> {
> int key;
> int count;
> string str;
> } tWork;
> list<test> L;
> list<test>::iterator qq;
>
> bool keyMatched(??????????????, ?????????)
> {
> ?????????????
> }
>
> int main(void)
> {
> char str[100];
>
> for (int ii = 1; ii <= 10; ii++)
> {
> tWork.count = 0, tWork.key = ii;
> sprintf(str, "Test string #%d", ii);
> tWork.str = str;
> L.push_back(tWork);
> } // for
> int jj = 5;
> qq = find_if(L.begin(), L.end(), keyMatched);
// where is "5" passed...and how?
>
> return 0;
> }
>
> So, how do I code a comparator routine (e.g. keyMatched) that
passes the currently referenced pointer in the find_if the value which I
want to test for?

STL Algorithms as find_if( ) needs predicate for its functionality. A
predicate is nothing more like another little class with overloaded
operator()() which returns a type which STL Algorithm needs - bool in
your example. Now STL Algorithms take your predicate and by means of
operator()() checks whether it returns true or fault with in similar way
as "if". If the predicate returns true find_if() returns the iterator to
your containers list<test>

Now I think your Predicate should look like (I assume it's true if all
members are equal to the sample !!!! ):

class Predicate {
private:
test value;

public:
Predicate(const test& vv) : value(vv) {}
bool operator()(const test& obj) {
return (value.key == obj.key)
&& (value.count == obj.count)
&& (value.str == obj.str);
}
};

The constructor initialize test value; and bool operator()(const test&
obj) compares ovject obj with interior object value initialized by
Constructor and returns true or fault if all values compared are equal.

somewhere in code:

test sample(10,20, "test");
Predicate pred(sample);

qq = find(L.begin(), L.end(), pred);

If it's not working I will try to write for you but not now, sorry. Try
to understand what predicate is and how it works.

I hope it's been more clear for you now.
 
Z

ZikO

Regretfully, I don't know what you're suggesting...or how to do such
a thing. Can you provide an example?

I mean if you have your class you can define operator as member function
of that class or just global function and as a friend to that class:

1) bool operator==() as a member function
class A {
int i;

public:
A(cont int& ii) : i(ii) {}
// first arg already defined as type of A
bool operator==(const int& ii) {
return (i == ii);
}
};

2) bool operator==() as a global function
class A {
int i;

public:
A(const int& ii) : i(ii) {}
// declaration of operator==() as a friend
friend bool operator==(const A& a, const int& ii);
};
// here definition of the function
bool operator==(const A& a, const int& ii) {
return (a.i == ii);
}

int main() {
A a(10), b(9);
if(a == 10); // <-- TRUE
if(a == 9); // false
if(b == 9); // TRUE
}
Best
 
M

Mike Copeland

Try something along the lines
struct my_predicate {
int k_;

my_predicate(int k) : k_(k) {}

bool operator()(const test& t)
{
return t.key==k_;
}
};

This way you get an object that "behaves" like a function but in fact
has some state.

This is _exactly_ what I needed, thanks! I don't quite understand
what it means (the ": k_(K) {}" syntax), but I can use such code as a
basis for the work I'm doing.
You should get a book that covers programming with the STL.

I have several, (but) their sizes and style are overwhelming to this
very old (69) long-time procedural programmer. Such new paradigms are
pretty difficult to grasp...8<{{
Anyway, I do appreciate your aid here, as well as others' who have
posted.
 
Ad

Advertisements

R

red floyd

Mike said:
This is _exactly_ what I needed, thanks! I don't quite understand
what it means (the ": k_(K) {}" syntax), but I can use such code as a
basis for the work I'm doing.

What book are you reading that doesn't discuss initialization lists?
Google for it, if you need to.
 
Ad

Advertisements

S

SG

I'd like to add that the function call operator "operator()" for such
predicates should be const. I forgot to include "const" in the first
version. Make it

bool operator()(const test& t) const
   I have several, (but) their sizes and style are overwhelming to this
very old (69) long-time procedural programmer.  Such new paradigms are
pretty difficult to grasp...8<{{

I see. I have only read four C++ related books so I don't have a good
overview of the books' quality distribution. But I think there's a
lot out there that isn't worth buying. You might want to check out
some book recommendations

( http://www.parashift.com/c++-faq-lite/how-to-learn-cpp.html#faq-28.4
)

and get yourself some quality ones. They can save you a lot of trial-
and-error and improve your coding skills quickly.


Cheers!
SG
 

Top