Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > problem on creating functor for std::sort

Reply
Thread Tools

problem on creating functor for std::sort

 
 
lok
Guest
Posts: n/a
 
      12-01-2003
i have a class:

template <class T1, class T2>
class CPairMapping {
public:
typedef std:air<T1, T2> ValuePair_t;
typedef std::vector<ValuePair_t> ValueList_t;
typedef std::binary_function< ValuePair_t, ValuePair_t, bool> ValuePair_IsLess;

void SortAscend(const ValuePair_IsLess& isLess_) {
std::sort(Map.begin(), Map.end(), isLess_);
}

// skip other funciton like add,delete,lookup...
protected:
ValueList_t Map;
};

i want to sort the Map with a functor supplied by the caller of SortAscend()


i created a functor:
typedef COne2ManyMapping<int, int> INT2INTMap;
class INT2INTMap_IsLess: public INT2INTMap::ValuePair_IsLess {
public:
bool operator() (INT2INTMap::ValuePair_t lhs_,INT2INTMap::ValuePair_t rhs_)
{
return true;
}
};

up to now, no compile or link error
but if i call the SortAscend loke this:
INT2INTMap a;
a.AddEntry(1, 2);
a.AddEntry(3, 4);
a.SortAscend( INT2INTMap_IsLess() );

my vc++ 6.0 compiler reported:
error C2064: term does not evaluate to a function
see reference to function template instantiation '
void __cdecl std::_Unguarded_insert(
struct std:air<int,int> *,
struct std:air<int,int>,
struct std::binary_function<
struct std:air<int,int>,
struct std:air<int,int>,
bool
>

)
' being compiled

what is the problem ?
thx
 
Reply With Quote
 
 
 
 
Rolf Magnus
Guest
Posts: n/a
 
      12-01-2003
lok wrote:

> i have a class:
>
> template <class T1, class T2>
> class CPairMapping {
> public:
> typedef std:air<T1, T2> ValuePair_t;
> typedef std::vector<ValuePair_t> ValueList_t;
> typedef std::binary_function< ValuePair_t, ValuePair_t, bool>
> ValuePair_IsLess;
>
> void SortAscend(const ValuePair_IsLess& isLess_) {
> std::sort(Map.begin(), Map.end(), isLess_);
> }
>
> // skip other funciton like add,delete,lookup...
> protected:
> ValueList_t Map;
> };
>
> i want to sort the Map with a functor supplied by the caller of
> SortAscend()
>
>
> i created a functor:
> typedef COne2ManyMapping<int, int> INT2INTMap;
> class INT2INTMap_IsLess: public INT2INTMap::ValuePair_IsLess {
> public:
> bool operator() (INT2INTMap::ValuePair_t
> lhs_,INT2INTMap::ValuePair_t rhs_)
> {
> return true;
> }
> };
>
> up to now, no compile or link error
> but if i call the SortAscend loke this:
> INT2INTMap a;
> a.AddEntry(1, 2);
> a.AddEntry(3, 4);
> a.SortAscend( INT2INTMap_IsLess() );
>
> my vc++ 6.0 compiler reported:
> error C2064: term does not evaluate to a function
> see reference to function template instantiation '
> void __cdecl std::_Unguarded_insert(
> struct std:air<int,int> *,
> struct std:air<int,int>,
> struct std::binary_function<
> struct std:air<int,int>,
> struct std:air<int,int>,
> bool
> >

> )
> ' being compiled
>
> what is the problem ?


Your operator() is not const, so it isn't considered when std::sort
tries to call your function object.

 
Reply With Quote
 
 
 
 
lok
Guest
Posts: n/a
 
      12-01-2003

"Rolf Magnus" <(E-Mail Removed)> wrote in message
news:bqfcoh$uhc$02$(E-Mail Removed)-online.com...
> lok wrote:
>
> > i have a class:
> >
> > template <class T1, class T2>
> > class CPairMapping {
> > public:
> > typedef std:air<T1, T2> ValuePair_t;
> > typedef std::vector<ValuePair_t> ValueList_t;
> > typedef std::binary_function< ValuePair_t, ValuePair_t, bool>
> > ValuePair_IsLess;
> >
> > void SortAscend(const ValuePair_IsLess& isLess_) {
> > std::sort(Map.begin(), Map.end(), isLess_);
> > }
> >
> > // skip other funciton like add,delete,lookup...
> > protected:
> > ValueList_t Map;
> > };
> >
> > i want to sort the Map with a functor supplied by the caller of
> > SortAscend()
> >
> >
> > i created a functor:
> > typedef COne2ManyMapping<int, int> INT2INTMap;
> > class INT2INTMap_IsLess: public INT2INTMap::ValuePair_IsLess {
> > public:
> > bool operator() (INT2INTMap::ValuePair_t
> > lhs_,INT2INTMap::ValuePair_t rhs_)
> > {
> > return true;
> > }
> > };
> >
> > up to now, no compile or link error
> > but if i call the SortAscend loke this:
> > INT2INTMap a;
> > a.AddEntry(1, 2);
> > a.AddEntry(3, 4);
> > a.SortAscend( INT2INTMap_IsLess() );
> >
> > my vc++ 6.0 compiler reported:
> > error C2064: term does not evaluate to a function
> > see reference to function template instantiation '
> > void __cdecl std::_Unguarded_insert(
> > struct std:air<int,int> *,
> > struct std:air<int,int>,
> > struct std::binary_function<
> > struct std:air<int,int>,
> > struct std:air<int,int>,
> > bool
> > >

> > )
> > ' being compiled
> >
> > what is the problem ?

>
> Your operator() is not const, so it isn't considered when std::sort
> tries to call your function object.
>


thx for your rely

i changed the operator() to this:
bool operator() (INT2INTMap::ValuePair_t lhs_,INT2INTMap::ValuePair_t rhs_)
const
{
return true;
}

the same error still occured


 
Reply With Quote
 
Rob Williscroft
Guest
Posts: n/a
 
      12-01-2003
lok wrote in news:(E-Mail Removed) om:

> i have a class:
>
> template <class T1, class T2>
> class CPairMapping {
> public:
> typedef std:air<T1, T2> ValuePair_t;
> typedef std::vector<ValuePair_t> ValueList_t;
> typedef std::binary_function< ValuePair_t, ValuePair_t, bool>
> ValuePair_IsLess;
>
> void SortAscend(const ValuePair_IsLess& isLess_) {
> std::sort(Map.begin(), Map.end(), isLess_);


This isn't going to work std::binary_function< > isn't a binary function
its a base class for function object's that *only* supplies some
typedef's that describe the arguments and return values.

It does *NOT* have a virtual operator () (T const &, T const &) const.

You need to pass std::sort() a genuine functor.

std::less< ValuePair_t >() would be a good start.

std::sort(Map.begin(), Map.end(), std::less< ValuePair_t >() );


> }
>
> // skip other funciton like add,delete,lookup...
> protected:
> ValueList_t Map;
> };
>
> i want to sort the Map with a functor supplied by the caller of
> SortAscend()
>


You can a make SortAscend() a template member function (uppgrade your
compiler first) or make a functor with a virtual operator () ...


>
> i created a functor:
> typedef COne2ManyMapping<int, int> INT2INTMap;
> class INT2INTMap_IsLess: public INT2INTMap::ValuePair_IsLess {
> public:
> bool operator() (INT2INTMap::ValuePair_t
> lhs_,INT2INTMap::ValuePair_t rhs_) {
> return true;
> }
> };


Make operator () a const member, also unless you like writing programmes
that hang or crash make it a valid Ordering function (model a < b) simply
returning true is nonsence.

std::sort(Map.begin(), Map.end(), INT2INTMap_IsLess() );

>
> up to now, no compile or link error
> but if i call the SortAscend loke this:
> INT2INTMap a;
> a.AddEntry(1, 2);
> a.AddEntry(3, 4);
> a.SortAscend( INT2INTMap_IsLess() );
>
> my vc++ 6.0 compiler reported:
> error C2064: term does not evaluate to a function


Yup std::binary_function<> isn't a functor.

> see reference to function template instantiation '
> void __cdecl std::_Unguarded_insert(
> struct std:air<int,int> *,
> struct std:air<int,int>,
> struct std::binary_function<
> struct std:air<int,int>,
> struct std:air<int,int>,
> bool
> >

> )
> ' being compiled
>


HTH.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
 
Reply With Quote
 
lok
Guest
Posts: n/a
 
      12-01-2003

"Rob Williscroft" <(E-Mail Removed)> wrote in message
news:Xns9444BA3ED6E91ukcoREMOVEfreenetrtw@195.129. 110.130...
> lok wrote in news:(E-Mail Removed) om:
>
> > i have a class:
> >
> > template <class T1, class T2>
> > class CPairMapping {
> > public:
> > typedef std:air<T1, T2> ValuePair_t;
> > typedef std::vector<ValuePair_t> ValueList_t;
> > typedef std::binary_function< ValuePair_t, ValuePair_t, bool>
> > ValuePair_IsLess;
> >
> > void SortAscend(const ValuePair_IsLess& isLess_) {
> > std::sort(Map.begin(), Map.end(), isLess_);

>
> This isn't going to work std::binary_function< > isn't a binary function
> its a base class for function object's that *only* supplies some
> typedef's that describe the arguments and return values.
>
> It does *NOT* have a virtual operator () (T const &, T const &) const.
>
> You need to pass std::sort() a genuine functor.
>
> std::less< ValuePair_t >() would be a good start.
>
> std::sort(Map.begin(), Map.end(), std::less< ValuePair_t >() );


thx for your reply
i realize the problem (though not completely understand...)
but i need my own less comparison (that's why i want to create a
INT2INTMap_IsLess functor)

>
>
> > }
> >
> > // skip other funciton like add,delete,lookup...
> > protected:
> > ValueList_t Map;
> > };
> >
> > i want to sort the Map with a functor supplied by the caller of
> > SortAscend()
> >

>
> You can a make SortAscend() a template member function (uppgrade your
> compiler first) or make a functor with a virtual operator () ...


i think this is the direction to go
can u explain further ? thx

>
>
> >
> > i created a functor:
> > typedef COne2ManyMapping<int, int> INT2INTMap;
> > class INT2INTMap_IsLess: public INT2INTMap::ValuePair_IsLess {
> > public:
> > bool operator() (INT2INTMap::ValuePair_t
> > lhs_,INT2INTMap::ValuePair_t rhs_) {
> > return true;
> > }
> > };

>
> Make operator () a const member, also unless you like writing programmes
> that hang or crash make it a valid Ordering function (model a < b) simply
> returning true is nonsence.


it just a test code to make the code more simple


>
> std::sort(Map.begin(), Map.end(), INT2INTMap_IsLess() );
>
> >
> > up to now, no compile or link error
> > but if i call the SortAscend loke this:
> > INT2INTMap a;
> > a.AddEntry(1, 2);
> > a.AddEntry(3, 4);
> > a.SortAscend( INT2INTMap_IsLess() );
> >
> > my vc++ 6.0 compiler reported:
> > error C2064: term does not evaluate to a function

>
> Yup std::binary_function<> isn't a functor.
>
> > see reference to function template instantiation '
> > void __cdecl std::_Unguarded_insert(
> > struct std:air<int,int> *,
> > struct std:air<int,int>,
> > struct std::binary_function<
> > struct std:air<int,int>,
> > struct std:air<int,int>,
> > bool
> > >

> > )
> > ' being compiled
> >

>
> HTH.
>
> Rob.
> --
> http://www.victim-prime.dsl.pipex.com/



 
Reply With Quote
 
lok
Guest
Posts: n/a
 
      12-02-2003
i modified the code as follow:
==================================
#include <vector>
#include <functional>
#include <string>
using std::string;

template <class T1, class T2 >
class CPairMapping {
public:
typedef std:air<T1, T2 > ValuePair_t;
typedef std::vector<ValuePair_t > ValueList_t;

class ValuePair_IsLess {
public:
virtual bool operator() (const ValuePair_t& lhs_,const ValuePair_t&
rhs_) const;
};

void SortAscend(const ValuePair_IsLess* isLess_) {
std::sort(Map.begin(), Map.end(), *isLess_);
}
protected:
ValueList_t Map;
};

typedef CPairMapping< string, string > STR2STRMap;

class STR2STRMap_IsLess: public STR2STRMap::ValuePair_IsLess {
public:
bool operator() (const STR2STRMap::ValuePair_t& lhs_, const
STR2STRMap::ValuePair_t& rhs_) const {
return lhs_.first().size() < rhs_.first().size(); // #error line
}
};


int main() {
STR2STRMap a;
STR2STRMap_IsLess isLess;
a.SortAscend( &isLess );
return 0;
}
==================================
now vc compiler reported at #error line:
error C2064: term does not evaluate to a function
error C2228: left of '.size' must have class/struct/union type
error C2064: term does not evaluate to a function
error C2228: left of '.size' must have class/struct/union type

it seem compiler doesnt recognize STR2STRMap::ValuePair_t is a pair<
string, string > object

how can i solve this error ?
thx
 
Reply With Quote
 
Rob Williscroft
Guest
Posts: n/a
 
      12-02-2003
lok wrote in news:(E-Mail Removed) om:

>
> i modified the code as follow:
> ==================================


Firstly my appologiess, I gave bad advise, makeing operator() virtual
was not a good idea as functors are mostly passed by value (so that
an ordinary function is also a functor), so slicing would occur
and what gets passed to std::sort is the base class with the
original operator ().

The following is a fix (of sorts) but it has no real advantage
over using a simple function pointer. Though it could if you need
to make the functor more complex.

#include <vector>
#include <functional>
#include <algorithm> // std::sort()
#include <string>

using std::string;

template <class T1, class T2 >
class CPairMapping
{
public:

typedef std:air<T1, T2 > ValuePair_t;
typedef std::vector< ValuePair_t > ValueList_t;

class ValuePair_IsLess :
std::binary_function<
ValuePair_t const &, ValuePair_t const &, bool
>

{
protected:

typedef
bool (*m_cmp_t)(
ValuePair_t const &lhs_, ValuePair_t const & rhs_
)
;
m_cmp_t m_cmp;

public:

ValuePair_IsLess( m_cmp_t cmp ) : m_cmp( cmp ) {}

bool operator() (
ValuePair_t const &lhs_, ValuePair_t const &rhs_
) const
{
return m_cmp( lhs_, rhs_ );
}
};

void SortAscend( ValuePair_IsLess isLess_ )
{
std::sort( Map.begin(), Map.end(), isLess_ );
}

protected:

ValueList_t Map;
};

typedef CPairMapping< string, string > STR2STRMap;

class STR2STRMap_IsLess: public STR2STRMap::ValuePair_IsLess
{
static bool cmp(
STR2STRMap::ValuePair_t const &lhs_,
STR2STRMap::ValuePair_t const &rhs_
)
{
return lhs_.first.size() < rhs_.first.size(); // #error line

// note the lack of .first().size() ..


}

typedef STR2STRMap::ValuePair_IsLess base_t;

public:

STR2STRMap_IsLess() : base_t( cmp ) {}
};


int main()
{
STR2STRMap a;
STR2STRMap_IsLess isLess;
a.SortAscend( isLess );
return 0;
}


Here's a simple function version, there is *alot* less cruft if
you really don't need it.


#include <vector>
#include <functional>
#include <algorithm> // std::sort()
#include <string>

using std::string;

template <class T1, class T2 >
class CPairMapping
{
public:

typedef std:air<T1, T2 > ValuePair_t;
typedef std::vector< ValuePair_t > ValueList_t;

typedef bool (*ValuePair_IsLess)(
ValuePair_t const &lhs_, ValuePair_t const & rhs_
);

void SortAscend( ValuePair_IsLess isLess_ )
{
std::sort( Map.begin(), Map.end(), isLess_ );
}

protected:

ValueList_t Map;
};

typedef CPairMapping< string, string > STR2STRMap;

bool STR2STRMap_IsLess(
STR2STRMap::ValuePair_t const &lhs_,
STR2STRMap::ValuePair_t const & rhs_
)
{
return lhs_.first.size() < rhs_.first.size();
}

int main()
{
STR2STRMap a;
//STR2STRMap_IsLess isLess;
a.SortAscend( STR2STRMap_IsLess );
return 0;
}

Rob.
--
http://www.victim-prime.dsl.pipex.com/
 
Reply With Quote
 
lok
Guest
Posts: n/a
 
      12-02-2003
after some little modification,
no compile, link or runtime error now
the code are follow:
=====================
#include <vector>
#include <functional>
#include <string>
using std::string;

template <class T1, class T2 >
class CPairMapping {
public:
typedef std:air<T1, T2 > ValuePair_t;
typedef std::vector<ValuePair_t > ValueList_t;

class ValuePair_IsLess {
public:
virtual bool operator() (const ValuePair_t& lhs_,const ValuePair_t&
rhs_) const {
return lhs_ < rhs_;
}
};

void SortAscend(const ValuePair_IsLess& isLess_) {
std::sort(Map.begin(), Map.end(), isLess_);
}
protected:
ValueList_t Map;
};

typedef CPairMapping< string, string > STR2STRMap;

class STR2STRMap_IsLess: public STR2STRMap::ValuePair_IsLess {
public:
bool operator() (const STR2STRMap::ValuePair_t& lhs_, const
STR2STRMap::ValuePair_t& rhs_) const {
return lhs_.first.size() < rhs_.first.size();
}
};

int main() {
STR2STRMap a;
STR2STRMap_IsLess isLess;
a.SortAscend( &isLess );
}
=====================
but in debug mode, i found std::sort called the operator() of
CPairMapping::ValuePair_IsLess instead of the operator() of
STR2STRMap_IsLess
it seem the dynamic binding of virtual function failed to work
is this because a new CPairMapping::ValuePair_IsLess is created to
pass to the std::sort funciton ?

how to solve this problem ?

thx
 
Reply With Quote
 
Rob Williscroft
Guest
Posts: n/a
 
      12-02-2003
lok wrote in news:(E-Mail Removed) om:

> after some little modification,
> no compile, link or runtime error now
> the code are follow:

[snip]
> but in debug mode, i found std::sort called the operator() of
> CPairMapping::ValuePair_IsLess instead of the operator() of
> STR2STRMap_IsLess
> it seem the dynamic binding of virtual function failed to work
> is this because a new CPairMapping::ValuePair_IsLess is created to
> pass to the std::sort funciton ?
>
> how to solve this problem ?
>


This works on the 3 conpilers I tried, (unfortunatly I haven't got
VC++ 6.0). See the comments inline:

#include <vector>
#include <functional>
#include <algorithm> /* forgot this again (std::sort) */
#include <string>
#include <iostream>

using std::string;

template <class T1, class T2 >
class CPairMapping
{
public:

typedef std:air<T1, T2 > ValuePair_t;
typedef std::vector<ValuePair_t > ValueList_t;
typedef typename std::vector<ValuePair_t >::iterator iterator;


class ValuePair_IsLess
{
public:
virtual bool operator() (
const ValuePair_t& lhs_,const ValuePair_t& rhs_
) const
{
return lhs_ < rhs_;
}
};

void SortAscend(const ValuePair_IsLess& isLess_)
{
/* This is the trick,
force std::sort to take a Comparitor by reference
*/
std::sort<
iterator, ValuePair_IsLess const &
>(

Map.begin(), Map.end(), isLess_
)
;
}

void add( T1 const &a, T2 const &b )
{
Map.push_back( ValuePair_t( a, b ) );
}

iterator begin() { return Map.begin(); }
iterator end() { return Map.end(); }

protected:

ValueList_t Map;
};


typedef CPairMapping< string, string > STR2STRMap;

class STR2STRMap_IsLess: public STR2STRMap::ValuePair_IsLess
{
public:
bool operator() (
const STR2STRMap::ValuePair_t& lhs_,
const STR2STRMap::ValuePair_t& rhs_
) const
{
return lhs_.first.size() < rhs_.first.size();
}
};


template < typename Iterator >
std:stream &print_pairs( std:stream &os, Iterator ptr, Iterator lim
)
{

if ( ptr != lim ) for (;
{
os << "( " << ptr->first << ", " << ptr->second << " )";
if (++ptr == lim ) break;
os << ", ";
}
return os;
}


int main()
{
STR2STRMap a;
STR2STRMap_IsLess isLess;

a.add( "2", "a" );
a.add( "1", "b" );

print_pairs( std::cerr, a.begin(), a.end() ) << "\n";

a.SortAscend( isLess ); /* pass by ref */

print_pairs( std::cerr, a.begin(), a.end() ) << "\n";
}




Rob.
--
http://www.victim-prime.dsl.pipex.com/
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Creating a functor creator alan C++ 3 11-18-2007 03:48 PM
problem with library design: support both std::ptr_fun and functor Fei Liu C++ 5 08-21-2007 02:03 PM
Non-const "member functor" problem Lionel B C++ 2 12-01-2006 04:50 PM
Problem with functor in g++ IndyStef C++ 2 10-23-2006 12:29 PM
problem compiling functor with sort Joel C++ 2 10-08-2004 10:05 PM



Advertisments