|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| STL is hannering me flat - in need of assistance |
|
![]() xiuhcoatl Member since: 8/8/2001 From: San Jose, CA, United States |
||||
|
|
||||
| I have a vector, I want to sort it. When I try to compile I get this error (abbr): error C2664: '()' : cannot convert parameter 1 from 'class ModeInfo *' to 'class ModeInfo &' see reference to function template instantiation 'void __cdecl std::_Unguarded_insert(class ModeInfo ** ,class ModeInfo *,struct modeSort)' being compiled The call is made as such; m_modeList is declared; MODE_VECTOR is defined as:
typedef std::vector<ModeInfo *> MODE_VECTOR
MODE_VECTOR m_modeList;
std::sort( m_modeList.begin(), m_modeList.end(), modeSort() );
if the ModeInfo class is needed let me know and i'll post it - I didn't want to waste a lot of space displaying the declaration. Current troubleshooting: What bothers me is that the first term is the issue - the SGI guide for stl states that vector.begin() and vector.end() both return a const_iterator ( just pointing to different elements ). MSDN documentation reflects the same information - in fact sample code is shown using std::sort( eg.begin(), eg.end() ). That example sort just uses a "less than" instead of the binary_function but the terms in question are prototyped the same so this error makes no sense. Algorthm.h is as follows (formatted):
template<class _RI, class _Ty, class _Pr> inline
void _Sort_0(_RI _F, _RI _L, _Pr _P, _Ty *)
{
if (_L - _F <= _SORT_MAX)
_Insertion_sort(_F, _L, _P);
else
{_Sort(_F, _L, _P, (_Ty *)0);
_Insertion_sort(_F, _F + _SORT_MAX, _P);
for (_F += _SORT_MAX; _F != _L; ++_F)
_Unguarded_insert(_F, _Ty(*_F), _P);
}
}
if I was a betting man then I'd say that either the documentation was hosed, the SGI implementation is slightly different, or the _Unguarded_insert call is wrong. I am getting to like STL but am by no means an expert - thank you in advance for a solution or just a direction to help me figure this out. Sorry this post is a little lenghty.. #dth-0 [edited by - xiuhcoatl on May 1, 2002 1:14:15 AM] [edited by - xiuhcoatl on May 1, 2002 1:20:03 AM] [edited by - xiuhcoatl on May 1, 2002 1:21:00 AM] [edited by - xiuhcoatl on May 1, 2002 1:21:51 AM] [edited by - xiuhcoatl on May 1, 2002 1:24:38 AM] |
||||
|
||||
![]() Anonymous Poster |
||||
|
||||
| Judging from the info that you have given, I'd bet that one of your problems is with your declaration of the vector. Since the vector, like much of the other STL classes, is a template, you always need to give it a template argument like so: typedef std::vector<int> MODE_VECTOR; 'int' can, of course, be replaced by any type (even your own types if they overload the proper operators). -D |
||||
|
||||
![]() xiuhcoatl Member since: 8/8/2001 From: San Jose, CA, United States |
||||
|
|
||||
| Apologies - The typedef for the MODE_VECTOR is properly done - I didn't format my post correctly and the chevrons got removed. Once I find the posting guide I'll correct the original post. #dth-0 |
||||
|
||||
![]() xiuhcoatl Member since: 8/8/2001 From: San Jose, CA, United States |
||||
|
|
||||
| _GRRR_ figured it out - It's sort of like waiting for a bus and lighting a cigarette... Call should be: std::sort( *(m_modeList.begin()), *(m_modeList.end()), modeSort() ); or modeSort should deal with pointers instead of addresses.. My bad.. #dth-0 |
||||
|
||||
![]() cgoat Member since: 3/9/2002 |
||||
|
|
||||
quote: You're using this wrong. The correct call should look like: std::sort( m_modeList.begin(), m_modeList.end(), modeSort); modeSort is a function, so you want to pass the function address, which is modeSort WITHOUT the parentheses. modeSort should be a function looking like: bool modeSort(ModeList*& ptr1, ModeList*& ptr2); which would do the comparison using the pointers, and returns true if (*ptr1) < (*ptr2). |
||||
|
||||
![]() Stoffel Member since: 12/2/1999 From: San Diego, USA |
||||
|
|
||||
If modesort is a functor, the declaration is correct. The function needs to take pointers as parameters, though. Here's an example of how I usually do it:
#include <vector>
#include <algorithm>
using namespace std;
class Widget
{
int m_data; // some arbitrary data
public:
// I like making my class predicates members of the class
struct Predicate;
friend Widget::Predicate;
struct Predicate
{
bool operator () (const Widget *lhs, const Widget *rhs) const
{
return lhs->m_data < rhs->m_data;
}
};
};
void sortWidgetVector (vector<Widget*> &vec)
{
sort (vec.begin (), vec.end (), Widget::Predicate ());
}
Also, you can overload operator < for your class if there is only one way you're going to sort things, and then use a templated predicate that sorts pointed-to types. Scott Meyers has an example of this in his Effective STL book, but I don't have it handy right now--it's pretty easy to bang out yourself, though, or if someone wants to post it.. |
||||
|
||||
![]() xiuhcoatl Member since: 8/8/2001 From: San Jose, CA, United States |
||||
|
|
||||
modeSort was/is a functor and needed to be passed that way, it's declaration was the key and my oversight. I was trying to get a little cute and adhere to [item 22] but eventually just changed the modeSort functor to accept pointers. The use of a functor outweighed overloading the lessthan operator because it would be logically ambiguous in certain contexts. Final declaration looks like this in case anyone is interested:
// Function used to sort the modes in the desired order
struct modeSort : public std::binary_function<ModeInfo*, ModeInfo*, bool>
{
// operator()
// Functor to assist in sorting the ModeInfo objects.
// XXX - _ASSERT only verifies pointer non-null
bool operator()(ModeInfo* p1, ModeInfo* p2)
{
_ASSERT(p1);
_ASSERT(p2);
// By format first. High to Low.
if( p1->format > p2->format ) return false;
if( p1->format < p2->format ) return true;
// Then width High to Low
if( p1->Width() < p2->Width() ) return false;
if( p1->Width() > p2->Width() ) return true;
// Then Height High to Low
if( p1->Height() < p2->Height() ) return false;
if( p1->Height() > p2->Height() ) return true;
// XXX - This function is supposed to be irreflexible, or
// if( f(x,y) && f(y,x) ) == false then they are equal, test and determine
// what this should be.
return false;
}
};
call -
// Sort the list
std::sort( m_modeList.begin(), m_modeList.end(), modeSort() );
|
||||
|
||||
![]() Stoffel Member since: 12/2/1999 From: San Diego, USA |
||||
|
|
||||
| Ah, the hierarchical compare, beautiful stuff. I applaud your use of binary_function. I do have two suggestions: 1) Make the operator () a const function--it doesn't change any members of the struct, and some pickier compilers won't be able to use the functor if it's non-const. If Width () and Height () aren't constant functions, they should be. Also make the arguments const. It's not correct till it's const-correct. 2) I have a general form for the hierarchical compare that does less operations but has the same logical format as yours. This is very important because this function is called a huge number of times during a sort. Here's an example:
bool operator () (const ModeInfo *lhs, const ModeInfo *rhs) const
{
int compare = lhs->format - rhs->format;
if (compare)
return compare < 0;
compare = lhs->Width () - rhs->Width ();
if (compare)
return compare < 0;
return lhs->Height () < rhs->Height ();
}
This accomplishes the same thing, but with less conditional jumps for some reason. If you look at the generated assembly for the two versions of the functions, there's about a 15% reduction in calls using my method (on MSVC 6.0 at least). Your compiler mileage may vary. [edited by - Stoffel on May 2, 2002 12:05:21 PM] |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|