Board index » cppbuilder » find_if error searching for struct with matching member

find_if error searching for struct with matching member


2004-10-09 12:10:48 AM
cppbuilder57
A typical situation for me:
I have a struct or class which represents an individual record with
members for firstname, lastname, etc.
I build a vector of these records and want later to be able to search
for individual records with specified member info (firstname = "John"
or lastname = "Stanford", etc).
I can easily do this with std::find if I define operator()== to look
up based on one of the fields, but this is clearly not a good solution
- for one thing it allows only one lookup field.
Seems like std::find_if is the appropriate solution, but I am now
stuck with a compiler error telling me the line need a ;
First thought it could be due to a nested struct, so I removed TMatch
from the form class, but no difference in the results.
I would appreciate any help, including a better basic approach. (Can I
do this with just function adapters and avoid functions dedicated to
searching for specific fields?)
Thanks.
- Leo
Here's my code:
//Unit1.h:
#ifndef Unit1H
#define Unit1H
#include <Classes.hpp>
#include <Controls.hpp>
#include <ExtCtrls.hpp>
#include <ComCtrls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <vector>
struct TMatch {
AnsiString Data;
TTreeNode* Node;
bool equalsNode( TTreeNode* );
};
class TForm1 : public TForm
{
__published:
private:
std::vector<TMatch>Matches;
std::vector<TMatch>::iterator TMatchIterator;
public:
__fastcall TForm1( TComponent* Owner );
};
extern PACKAGE TForm1 *Form1;
#endif
//Unit1.cpp:
#include <vcl.h>
#pragma hdrstop
#include <algorithm>
#include <functional>
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
bool TMatch::equalsNode( TTreeNode *node )
{
return node == Node;
}
TForm1 *Form1;
__fastcall TForm1::TForm1( TComponent* Owner ) : TForm( Owner )
{
TTreeNode *node;
TMatchIterator it =
std::find_if (
Matches.begin(),
Matches.end(),
std::bind2nd(
std::mem_fun_ref( &TMatch::equalsNode ),
node
)
); // ERROR
}
[C++ Error] Unit1.cpp(19): E2379 Statement missing ;
 
 

Re:find_if error searching for struct with matching member

Leo Siefert wrote:
Quote
struct TMatch {
AnsiString Data;
TTreeNode* Node;
bool equalsNode( TTreeNode* );
};
This function works with pointers.
Quote
class TForm1 : public TForm
{
__published:
private:
std::vector<TMatch>Matches;
std::vector<TMatch>::iterator TMatchIterator;
public:
__fastcall TForm1( TComponent* Owner );
};
The vector stores objects-by-value.
Functor should be passing objects by reference-to-const.
Quote
__fastcall TForm1::TForm1( TComponent* Owner ) : TForm( Owner )
{
TTreeNode *node;
TMatchIterator it =
std::find_if (
Matches.begin(),
Matches.end(),
std::bind2nd(
std::mem_fun_ref( &TMatch::equalsNode ),
node
)
); // ERROR
}
I strongly recommend taking a look at the boost::bind library, soon to
be part of the standard library Technical Report. It is *much* simpler
than bind1st/2nd. mem_fun_ref and all that. Everything is handled by
the single bind template.
std::find_if (
Matches.begin(),
Matches.end(),
boost::bind( &TMatch::equalsNode, node, _1 )
)
);
AlisdairM(TeamB)
 

Re:find_if error searching for struct with matching member

Leo Siefert wrote:
Quote
I would appreciate any help, including a better basic approach. (Can I
do this with just function adapters and avoid functions dedicated to
searching for specific fields?)
I think find_if is definitely the right basic approach. This is exactly
what it's for. I think you could do it with just function adapters
(adapting a getter and composing it with equals and bind2nd) if you use
some of the boost classes but not with plain old standard library C++.
As for the error, I haven't actually compiled this, but the following
things strike me looking at it.
Quote
bool equalsNode( TTreeNode* );
Should probably be:
bool equalsNode(const TTreeNode*) const;
Quote
std::vector<TMatch>::iterator TMatchIterator;
[...]
TMatchIterator it =
Is TMatchIterator supposed to be a type or a member? You've declared it
as a member of the class but you're using it here like it's a type. I
suspect that's the cause of the error. The compiler is as confused as I
am. :-)
--
Gillmer J. Derge [TeamB]
 

{smallsort}

Re:find_if error searching for struct with matching member

On Fri, 08 Oct 2004 12:35:54 -0400, "Gillmer J. Derge [TeamB]"
< XXXX@XXXXX.COM >wrote:
Quote
>bool equalsNode( TTreeNode* );

Should probably be:

bool equalsNode(const TTreeNode*) const;
Agreed. Sometimes my consts arrive late, especially when the code is
not even compiling.
Quote
>std::vector<TMatch>::iterator TMatchIterator;
[...]
>TMatchIterator it =

Is TMatchIterator supposed to be a type or a member?
Type - forgot the typedef in the declaration. Noticed just after
posting and thought I had deleted the post, but obviously I was not
successful at doing so. (Fridays can seem like long days.)
Thanks for spotting the error and the in-const-ancy.
- Leo
 

Re:find_if error searching for struct with matching member

On 8 Oct 2004 09:29:47 -0700, "Alisdair Meredith (TeamB)"
< XXXX@XXXXX.COM >wrote:
Quote
Leo Siefert wrote:

>struct TMatch {
>AnsiString Data;
>TTreeNode* Node;
>bool equalsNode( TTreeNode* );
>};

This function works with pointers.

>std::vector<TMatch>Matches;
>std::vector<TMatch>::iterator TMatchIterator;

The vector stores objects-by-value.
Functor should be passing objects by reference-to-const.
Not sure if I understand you here. while the vector does hold objects,
the TMatch object includes a TTreeNode*. There is also a TTreeNode*
being passed to the functor (which Gilmer pointed out should be
consted).
Quote
I strongly recommend taking a look at the boost::bind library, soon to
be part of the standard library Technical Report. It is *much* simpler
than bind1st/2nd. mem_fun_ref and all that. Everything is handled by
the single bind template.
That's high on my list of things to do when I have a spare minute or
two. If I understand you correctly, this would just simplify the one
line of (admittedly difficult to parse) code by substituting a single
adaptor for the two nested adaptors I used.
What I would really like to find is a way to avoid needing to have a
dedicated function for searching on each field of the data structure.
In this case, if I want to search for a match to the Data member it
seems that I need to add an additional functor to allow that. Not a
very scalable approach and I would like to find something better.
In fact, in the actual program I'm developing, Data is a
vector<AnsiString>with a corresponding map<AnsiString,int>to
translate fieldnames to position and there could be benefit to being
able to search for a string by index as in
Matches::Data[FieldMap['lastname']] == "Siefert". This would allow
changes to the data structure without changing the program code and
runtime binding of the field names.
Thanks for the help.
BTW - see Gilmer's answer and my response - the compile error has been
rectified, though I have yet to confirm that I am actually finding the
correct record.
- Leo
 

Re:find_if error searching for struct with matching member

Leo Siefert wrote:
Quote
What I would really like to find is a way to avoid needing to have a
dedicated function for searching on each field of the data structure.
Assuming that a getter doesn't count as a dedicated function, I think
something like this would work (untested, and I've never really used
boost::bind, but this looks like more or less the right idea) ...
bind(std::equals<TTreeNode*>(), node,
bind(mem_fun_ref(&TMatch::getNode), _1))
I think this should turn into something equivalent to:
std::equals<T>(node, x.getNode());
--
Gillmer J. Derge [TeamB]
 

Re:find_if error searching for struct with matching member

Leo Siefert < XXXX@XXXXX.COM >writes:
Quote
What I would really like to find is a way to avoid needing to have a
dedicated function for searching on each field of the data structure.
In this case, if I want to search for a match to the Data member it
seems that I need to add an additional functor to allow that. Not a
very scalable approach and I would like to find something better.
It does not have to be a member function, though. If you
decide--later--to add another sort ordering or comparison function,
you can do that in your own "user" code withotu touching the
declaration of the objects in the container.
--
Chris (TeamB);