472,328 Members | 1,029 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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

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 1528
"titancipher" <ja***********@gmail.com> wrote in message
news:11*********************@z14g2000cwz.googlegro ups.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 "dosomething" 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(unsigned n) : n(n) {}

int operator()(const 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_function< 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_function< 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_function< 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_function< 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
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...
7
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() {...
6
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...
1
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...
5
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...
3
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...
2
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...
14
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...
2
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...
8
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
by: tammygombez | last post by:
Hey everyone! I've been researching gaming laptops lately, and I must say, they can get pretty expensive. However, I've come across some great...
0
by: teenabhardwaj | last post by:
How would one discover a valid source for learning news, comfort, and help for engineering designs? Covering through piles of books takes a lot of...
0
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and...
0
by: CD Tom | last post by:
This only shows up in access runtime. When a user select a report from my report menu when they close the report they get a menu I've called Add-ins...
0
by: Naresh1 | last post by:
What is WebLogic Admin Training? WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge...
0
jalbright99669
by: jalbright99669 | last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made...
0
by: antdb | last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine In the overall architecture, a new "hyper-convergence" concept was...
1
by: Matthew3360 | last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...
0
by: AndyPSV | last post by:
HOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and on my computerHOW CAN I CREATE AN AI with an .executable...

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.