473,837 Members | 1,705 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Making a class that accepts a user-defined STL coparison function

I have a container that I wish to allow the user to specify a custom
comparison method very similar to std::less. However, I want it to
function more like memcmp (returning -1 0 1), and I want to be able to
vary the fields that are compared. The example below shows how I'd
like it to fit together.

struct fields
{
fields( int f1, int f2, int f3 ){ m_f[0] = f1; m_f[1] = f2; m_f[2]
= f3; }
int m_f[3];
};

template< typename T >
class Foo
{
public:
Foo( const T & t ) : m_t( t ){ }
int dosomething( const T & t )
{
// error: want to compare t by any of the 3 fields. the method
// passed in should handle which fields are compared.
if( t < m_t ) return -1;
else if( t > m_t ) return 1;
else return 0;
}
protected:
const T m_t;
};

int main(int argc, char* argv[])
{
Foo< fields > foo( fields( 3, 2, 1 ) );
foo.dosomething ( fields( 1, 2, 3 ) );
return 0;
}

Jul 23 '05 #1
4 1613
"titanciphe r" <ja***********@ gmail.com> wrote in message
news:11******** *************@z 14g2000cwz.goog legroups.com...
I have a container that I wish to allow the user to specify a custom
comparison method very similar to std::less. However, I want it to
function more like memcmp (returning -1 0 1), and I want to be able to
vary the fields that are compared. The example below shows how I'd
like it to fit together.

struct fields
{
fields( int f1, int f2, int f3 ){ m_f[0] = f1; m_f[1] = f2; m_f[2]
= f3; }
int m_f[3];
};


If you need to compare objects of type 'fields' define comparison operators
for this type:

bool operator < (const fields& l, const fields& r)
{
/* return whatever logic comes here; */
}
bool operator > (const fields& l, const fields& r)
{
/* return whatever logic comes here; */
}
Regards,
Janusz
Jul 23 '05 #2
titancipher wrote:
I have a container that I wish to allow the user to specify a custom
comparison method very similar to std::less. However, I want it to
function more like memcmp (returning -1 0 1), and I want to be able to
vary the fields that are compared. The example below shows how I'd
like it to fit together.

struct fields
{
fields( int f1, int f2, int f3 ){ m_f[0] = f1; m_f[1] = f2; m_f[2]
= f3; }
int m_f[3];
};

template< typename T >
class Foo
{
public:
Foo( const T & t ) : m_t( t ){ }
int dosomething( const T & t )
{
// error: want to compare t by any of the 3 fields. the method
// passed in should handle which fields are compared.
if( t < m_t ) return -1;
else if( t > m_t ) return 1;
else return 0;
}
protected:
const T m_t;
};

int main(int argc, char* argv[])
{
Foo< fields > foo( fields( 3, 2, 1 ) );
foo.dosomething ( fields( 1, 2, 3 ) );
return 0;
}


You want to make your "dosomethin g" function a member template. For
example:

template <class Compare>
int dosomething( const T & t, const Compare & comp)
{
int result = comp(t, m_t) ;

if (result == 1)
std::cout << "greater" << std::endl ;
else if (result == -1)
std::cout << "less" << std::endl ;
else
std::cout << "equal" << std::endl ;
}

Then your user defined comparison objects will look something like this.

class compare_field
{
unsigned n ; // field to compare
public :
compare_field(u nsigned n) : n(n) {}

int operator()(cons t fields &f1, const fields &f2) const
{
if (f1.m_f[n] < f2.m_f[n])
return -1 ;
else if (f1.m_f[n] > f2.m_f[n])
return 1 ;
else
return 0 ;
}
} ;
You may then call dosomething in a manner similar to this :

Foo< fields > foo( fields( 3, 2, 1 ) );
foo.dosomething ( fields( 1, 2, 3 ), compare_field(0 ) );
foo.dosomething ( fields( 1, 2, 3 ), compare_field(1 ) );
foo.dosomething ( fields( 1, 2, 3 ), compare_field(2 ) );

-Alan
Jul 23 '05 #3
Hi Alan,
Thanks, what you describe would work. However, I was looking to
provide a more STL-like method. If you look at std::map, std::set,
etc., the method std::less is used as a default argument in the
template specification. What you propose would require passing a
compare_field(0 ) for each insert (i.e. 'dosomething').

I've done a little more thinking about it, and have a solution. I'll
post it. First, I create a class much like std::less called compare:

template< typename T >
class compare : public std::binary_fun ction< T, T, int >
{
public:
compare(){ }
public:
bool operator()( const T & lhs, const T & rhs ) const
{
if( lhs < rhs ) return -1;
else if( lhs < rhs ) return 1;
else return 0;
}
};

Then, I change Foo to use the binary function 'compare' by default:

template< typename T, class C = compare< T > >
class Foo
{
public:
Foo( const T & t ) : m_t( t ){ }

int foocmp( const T & t )
{
int c = compare( t, m_t );
if( c < 0 ) return -1;
else if( c > 0 ) return 1;
else return 0;
}
protected:
const T m_t;
const C compare;
};

Then, because the default compare is not adequate to compare my fields
class (it does not compare individual fields), I write a custom compare
per-field. Field 0 compare is below:

class cmp_field_0 : public std::binary_fun ction< fields, fields, int >
{
public:
cmp_field_0() : m_n( 0 ) { }
public:
int operator()( const fields & lhs, const fields & rhs ) const
{
if( lhs.m_f[ m_n ] < rhs.m_f[ m_n ] ) return -1;
else if( lhs.m_f[ m_n ] < rhs.m_f[ m_n ] ) return 1;
else return 0;
}
private:
int m_n;
};

The usage is now:

Foo< fields, cmp_field_0 > foo( fields( 3, 2, 1 ) );
foo.dosomething ( fields( 1, 2, 3 ) );

However, I would have to create a cmp_field_1, cmp_field_2, etc., and
that's that's still not great. I can then change the cmp_field to
include another template argument to indicate the field to test:

template< int F >
class cmp_field : public std::binary_fun ction< fields, fields, int >
{
public:
cmp_field() : m_n( F ) { }
public:
int operator()( const fields & lhs, const fields & rhs ) const
{
if( lhs.m_f[ m_n ] < rhs.m_f[ m_n ] ) return -1;
else if( lhs.m_f[ m_n ] < rhs.m_f[ m_n ] ) return 1;
else return 0;
}
private:
int m_n;
};

The usage is now:

Foo< fields, cmp_field< 0 > > foo( fields( 3, 2, 1 ) );
foo.dosomething ( fields( 1, 2, 3 ) );

The above achieves making a STL-like comparison operator to compare
different fields. However, I'd still be interesting in seeing someone
else's angle on this.

Kind Regards,
Jamie

Jul 23 '05 #4
Sorry, the default compare class is:
template< typename T >
class compare : public std::binary_fun ction< T, T, int >
{
public:
compare(){ }
public:
int operator()( const T & lhs, const T & rhs ) const
{
if( lhs < rhs ) return -1;
else if( lhs < rhs ) return 1;
else return 0;
}
};

Not 'bool' like previously specified.

Jul 23 '05 #5

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

Similar topics

1
5236
by: BJS | last post by:
Sorry for the cross-posting, but based on the number of people I have seen ask for a solution to this problem, I hope by cross-posting this, that it will help a lot of people out of a common problem. Have you ever wanted to use print to a file using the System.Drawing.Printing namespace only to find out that the only way to do it is by popping a dialog box through the PrintDialog? What if you want to print to file without user...
7
2667
by: newbiecpp | last post by:
Why this code cannot be compiled (under VC++ 7.0): class Outer { public: class Inner { public: Inner() : in_data(0) {} void action() { Outer::out_data++; // illegal reference to non-static
6
4080
by: zhixin_han | last post by:
Following warnings are found in my application: ..../adm_std_mo_descr.h:240: warning: non-static const member `const struct std_tee_t std_mo::tee' in class without a constructor ..../adm_std_mo_descr.h:244: warning: non-static const member `const char *const std_mo::name' in class without a constructor The header file looks as the following: typedef struct std_tee {
1
296
by: mt404 | last post by:
Hi, I was wondering if someone might be able to provide some guidance on how I could make an http request from a C# library. Basically I have a library which accepts a couple of arguments that I use to construct a dynamic http URL address. I wan't to then make a call to this address, capture the data stream it returns, and return that to the application which called the library. I know how to do most everything but I'm not sure how...
5
524
by: john | last post by:
I searched http://www.sellsbrothers.com. and could not find anything about this subject. How do I make C# User Controls Visible to Visual Basic 6.0 Applications? Thanks, John
3
1609
by: Tim Marsden | last post by:
Hi, I would like to be able to create a page which accepts user input. When to user press Submit, a long task is performed, and the results displayed on a new page. When the user presses Submit, can I put a "Waiting...." page out. The page requests some information from another source, when it gets the information back it displays it on the page.
2
1313
by: Dennis | last post by:
I have a control that inheirts from "Panel". I want to prevent the user from having access to the MoueUp event. I tried making a sub in my control that handles MyBase.MouseUp but still this event shows up as an event the user can use. Is there anyway to prevent users of this control from getting access to events such as MouseUp. Thanks. -- Dennis in Houston
14
3039
by: Paul Bromley | last post by:
Forgive my ignorance on this one as I am trying to use a Singleton class. I need to use this to have one instance of my Class running and I think I understand how to do this. My question however is can a singleton class have a number of paramterised constructors enabling me to pass in parameters or not? I am trying to use the following to send in a parmeter to a constructor, but getting an error with it. I have a feeling that I am not...
2
1168
by: RSH | last post by:
I have a situation where I am working with a user class and I need to reference the form. Is it best to pass the form object to the constructor of the class on instantiation, or to access it another way? Thanks, Ron
8
2971
by: flopbucket | last post by:
Hi, I want to provide a specialization of a class for any type T that is a std::map. template<typename T> class Foo { // ... };
0
10899
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10583
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10638
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9419
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, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
7012
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5680
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5862
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4481
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3128
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.