Doubts with sorting stl vector...
-
Hi everyone, I have a class like this:
// Header file
class CFoo
{
public:
CFoo();
~CFoo();
BOOL SortByName();
// Other functions declared here...protected:
std::vector<CRec*> m_Recs; // CRec is a class with CStrings, etc.private:
struct NameComparer
{
bool operator()(const CRec* A,const CRec* B)
{
return ((A->m_strName) < (B->m_strName));
}
};
};// CPP file
// Other functions are defined here...
BOOL CFoo::SortByName()
{
std::stable_sort(m_Recs.begin(), m_Recs.end(), NameComparer());return TRUE;
}
Now, basically, I am trying to properly write and use a predicate function (I think that's what they're called; please correct me if I'm wrong) in the context of calling
std::stable_sort
(and juststd::sort
for that matter). There are many helpful examples around, but they don't seem to cover dealing with a non-trivial class (or if they do I haven't 'gotten it' yet). In my case, I want to be able to sort the vector ofCRec
's according to several differentCRec
member variables (differentCString
s,int
s,double
s, etc.). My questions are: 1) Did I use proper coding techniques to solve the problem as I have shown here? 2) Is it the case that I need to add additionalstruct
s under theprivate
section ofCFoo
for each comparisonCFoo
member function I want to write (with the comparisons applied to thestd::vector m_Recs
and based on theCRec
members themselves actually)? 3) Why do I need to wrap the comparison functions in a struct? How does that fact relate tooperator()
, etc.? Thank you all again for reading and giving any advice, Best, :) Eric -
Hi everyone, I have a class like this:
// Header file
class CFoo
{
public:
CFoo();
~CFoo();
BOOL SortByName();
// Other functions declared here...protected:
std::vector<CRec*> m_Recs; // CRec is a class with CStrings, etc.private:
struct NameComparer
{
bool operator()(const CRec* A,const CRec* B)
{
return ((A->m_strName) < (B->m_strName));
}
};
};// CPP file
// Other functions are defined here...
BOOL CFoo::SortByName()
{
std::stable_sort(m_Recs.begin(), m_Recs.end(), NameComparer());return TRUE;
}
Now, basically, I am trying to properly write and use a predicate function (I think that's what they're called; please correct me if I'm wrong) in the context of calling
std::stable_sort
(and juststd::sort
for that matter). There are many helpful examples around, but they don't seem to cover dealing with a non-trivial class (or if they do I haven't 'gotten it' yet). In my case, I want to be able to sort the vector ofCRec
's according to several differentCRec
member variables (differentCString
s,int
s,double
s, etc.). My questions are: 1) Did I use proper coding techniques to solve the problem as I have shown here? 2) Is it the case that I need to add additionalstruct
s under theprivate
section ofCFoo
for each comparisonCFoo
member function I want to write (with the comparisons applied to thestd::vector m_Recs
and based on theCRec
members themselves actually)? 3) Why do I need to wrap the comparison functions in a struct? How does that fact relate tooperator()
, etc.? Thank you all again for reading and giving any advice, Best, :) EricIt's usually best to wait a few days before posting the same question again. And, surprisingly, an answer may not be know by the current CP members!
A rich person is not the one who has the most, but the one that needs the least.
-
Hi everyone, I have a class like this:
// Header file
class CFoo
{
public:
CFoo();
~CFoo();
BOOL SortByName();
// Other functions declared here...protected:
std::vector<CRec*> m_Recs; // CRec is a class with CStrings, etc.private:
struct NameComparer
{
bool operator()(const CRec* A,const CRec* B)
{
return ((A->m_strName) < (B->m_strName));
}
};
};// CPP file
// Other functions are defined here...
BOOL CFoo::SortByName()
{
std::stable_sort(m_Recs.begin(), m_Recs.end(), NameComparer());return TRUE;
}
Now, basically, I am trying to properly write and use a predicate function (I think that's what they're called; please correct me if I'm wrong) in the context of calling
std::stable_sort
(and juststd::sort
for that matter). There are many helpful examples around, but they don't seem to cover dealing with a non-trivial class (or if they do I haven't 'gotten it' yet). In my case, I want to be able to sort the vector ofCRec
's according to several differentCRec
member variables (differentCString
s,int
s,double
s, etc.). My questions are: 1) Did I use proper coding techniques to solve the problem as I have shown here? 2) Is it the case that I need to add additionalstruct
s under theprivate
section ofCFoo
for each comparisonCFoo
member function I want to write (with the comparisons applied to thestd::vector m_Recs
and based on theCRec
members themselves actually)? 3) Why do I need to wrap the comparison functions in a struct? How does that fact relate tooperator()
, etc.? Thank you all again for reading and giving any advice, Best, :) EricIn sum, your solution is okay. In general, check out these books for in-depth explanation on STL. The C++ Standard Library : A Tutorial and Reference by Nicolai M. Josuttis Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library by Scott Meyers Kuphryn
-
It's usually best to wait a few days before posting the same question again. And, surprisingly, an answer may not be know by the current CP members!
A rich person is not the one who has the most, but the one that needs the least.
-
In sum, your solution is okay. In general, check out these books for in-depth explanation on STL. The C++ Standard Library : A Tutorial and Reference by Nicolai M. Josuttis Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library by Scott Meyers Kuphryn
-
Hi David, I know. And I knew that I risked being rude, but I figured that since it was late when I left the post it might not get seen by many, so I took the chance. Anyhow, I take your point and I appreciate your feedback. Best, Eric
Cloaca wrote: And I knew that I risked being rude... It was being rude per se, it's just that with timezone differences and the like, it may take two full days before the post has been digested by everyone.
A rich person is not the one who has the most, but the one that needs the least.
-
Hi everyone, I have a class like this:
// Header file
class CFoo
{
public:
CFoo();
~CFoo();
BOOL SortByName();
// Other functions declared here...protected:
std::vector<CRec*> m_Recs; // CRec is a class with CStrings, etc.private:
struct NameComparer
{
bool operator()(const CRec* A,const CRec* B)
{
return ((A->m_strName) < (B->m_strName));
}
};
};// CPP file
// Other functions are defined here...
BOOL CFoo::SortByName()
{
std::stable_sort(m_Recs.begin(), m_Recs.end(), NameComparer());return TRUE;
}
Now, basically, I am trying to properly write and use a predicate function (I think that's what they're called; please correct me if I'm wrong) in the context of calling
std::stable_sort
(and juststd::sort
for that matter). There are many helpful examples around, but they don't seem to cover dealing with a non-trivial class (or if they do I haven't 'gotten it' yet). In my case, I want to be able to sort the vector ofCRec
's according to several differentCRec
member variables (differentCString
s,int
s,double
s, etc.). My questions are: 1) Did I use proper coding techniques to solve the problem as I have shown here? 2) Is it the case that I need to add additionalstruct
s under theprivate
section ofCFoo
for each comparisonCFoo
member function I want to write (with the comparisons applied to thestd::vector m_Recs
and based on theCRec
members themselves actually)? 3) Why do I need to wrap the comparison functions in a struct? How does that fact relate tooperator()
, etc.? Thank you all again for reading and giving any advice, Best, :) EricCloaca wrote: Is it the case that I need to add additional structs under the private section of CFoo for each comparison CFoo member function I want to write [...]? Yes. AFAIK every comparison need its own comparer (like you have with the NameComparer) Cloaca wrote: 3) Why do I need to wrap the comparison functions in a struct? How does that fact relate to operator(), etc.?
struct
does mean the same asclass, but everything is public by default
. As you only want a class with only one public operator, writing struct instead ofclass
does save you a whopping 6 keystrokes (7 for 'public' plus the ':', minus one becausestruct
is longer thanclass
. I think that is the only reason.
"We trained hard, but it seemed that every time we were beginning to form up into teams we would be reorganised. I was to learn later in life that we tend to meet any new situation by reorganising: and a wonderful method it can be for creating the illusion of progress, while producing confusion, inefficiency and demoralisation." -- Caius Petronius, Roman Consul, 66 A.D.
-
Cloaca wrote: And I knew that I risked being rude... It was being rude per se, it's just that with timezone differences and the like, it may take two full days before the post has been digested by everyone.
A rich person is not the one who has the most, but the one that needs the least.
-
Cloaca wrote: Is it the case that I need to add additional structs under the private section of CFoo for each comparison CFoo member function I want to write [...]? Yes. AFAIK every comparison need its own comparer (like you have with the NameComparer) Cloaca wrote: 3) Why do I need to wrap the comparison functions in a struct? How does that fact relate to operator(), etc.?
struct
does mean the same asclass, but everything is public by default
. As you only want a class with only one public operator, writing struct instead ofclass
does save you a whopping 6 keystrokes (7 for 'public' plus the ':', minus one becausestruct
is longer thanclass
. I think that is the only reason.
"We trained hard, but it seemed that every time we were beginning to form up into teams we would be reorganised. I was to learn later in life that we tend to meet any new situation by reorganising: and a wonderful method it can be for creating the illusion of progress, while producing confusion, inefficiency and demoralisation." -- Caius Petronius, Roman Consul, 66 A.D.
Hi jhwurmbach, Thanks for your reply. That makes sense, but it then makes me wonder why I need a class (or struct) at all to hold the comparison function. Why is it that I just can't declare the comparison function (just as a 'simple' member of
CFoo
) and pass it to thestable_sort()
call? I have been reading aboutoperator()
and functors, but I am not putting it all together yet, I guess. Does it have someting to do with the fact that functions passed to the algorithms can only have one parameter? I appreciate your help, thanks again! :) Eric -
Hi jhwurmbach, Thanks for your reply. That makes sense, but it then makes me wonder why I need a class (or struct) at all to hold the comparison function. Why is it that I just can't declare the comparison function (just as a 'simple' member of
CFoo
) and pass it to thestable_sort()
call? I have been reading aboutoperator()
and functors, but I am not putting it all together yet, I guess. Does it have someting to do with the fact that functions passed to the algorithms can only have one parameter? I appreciate your help, thanks again! :) Ericstds::sort is a template function. That means the arguments for the function determines what kind of code the compiler generates for the function (as opposed to a regular function, where the compiler always generates the same code). A template argument must be either a type or a constant--the compiler must be able to determine what the argument is at compile time, so it knows what code to generate. For the sort function, the template argument might have been a functor type or it might have been a constant that resolves to a function pointer. If you think about it, you can see how making the argument a type gives much more flexibility to the user of the template function, so that is the choice that the template designer made.
-
stds::sort is a template function. That means the arguments for the function determines what kind of code the compiler generates for the function (as opposed to a regular function, where the compiler always generates the same code). A template argument must be either a type or a constant--the compiler must be able to determine what the argument is at compile time, so it knows what code to generate. For the sort function, the template argument might have been a functor type or it might have been a constant that resolves to a function pointer. If you think about it, you can see how making the argument a type gives much more flexibility to the user of the template function, so that is the choice that the template designer made.
Hi antlers, Ahh. I think that puts it together for me. A function is of course not a type. But by using the 'struct method', you kind-of wrap the function in a type. And so it is acceptable to the algorithm at compile time. The syntax of operator() is the way a wrapped function can be exposed to the algorithm for use in, for example, a sort call as a comparison. And this minimal extra work is the small price to pay for a very flexible system of getting whatever might be needed into the templated algorithms. I see. Thanks very much for your help, I appreciate it! :) Best, Eric