By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,413 Members | 999 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,413 IT Pros & Developers. It's quick & easy.

problem on creating functor for std::sort

P: n/a
lok
i have a class:

template <class T1, class T2>
class CPairMapping {
public:
typedef std::pair<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::pair<int,int> *,
struct std::pair<int,int>,
struct std::binary_function<
struct std::pair<int,int>,
struct std::pair<int,int>,
bool

)
' being compiled

what is the problem ?
thx
Jul 22 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
lok wrote:
i have a class:

template <class T1, class T2>
class CPairMapping {
public:
typedef std::pair<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::pair<int,int> *,
struct std::pair<int,int>,
struct std::binary_function<
struct std::pair<int,int>,
struct std::pair<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.

Jul 22 '05 #2

P: n/a
lok

"Rolf Magnus" <ra******@t-online.de> wrote in message
news:bq*************@news.t-online.com...
lok wrote:
i have a class:

template <class T1, class T2>
class CPairMapping {
public:
typedef std::pair<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::pair<int,int> *,
struct std::pair<int,int>,
struct std::binary_function<
struct std::pair<int,int>,
struct std::pair<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
Jul 22 '05 #3

P: n/a
lok wrote in news:69**************************@posting.google.c om:
i have a class:

template <class T1, class T2>
class CPairMapping {
public:
typedef std::pair<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::pair<int,int> *,
struct std::pair<int,int>,
struct std::binary_function<
struct std::pair<int,int>,
struct std::pair<int,int>,
bool
>

)
' being compiled


HTH.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #4

P: n/a
lok

"Rob Williscroft" <rt*@freenet.REMOVE.co.uk> wrote in message
news:Xn**********************************@195.129. 110.130...
lok wrote in news:69**************************@posting.google.c om:
i have a class:

template <class T1, class T2>
class CPairMapping {
public:
typedef std::pair<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::pair<int,int> *,
struct std::pair<int,int>,
struct std::binary_function<
struct std::pair<int,int>,
struct std::pair<int,int>,
bool
>

)
' being compiled


HTH.

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

Jul 22 '05 #5

P: n/a
lok
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::pair<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
Jul 22 '05 #6

P: n/a
lok wrote in news:69**************************@posting.google.c 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::pair<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::pair<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/
Jul 22 '05 #7

P: n/a
lok
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::pair<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
Jul 22 '05 #8

P: n/a
lok wrote in news:69**************************@posting.google.c 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::pair<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::ostream &print_pairs( std::ostream &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/
Jul 22 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.