I have the following list of person class to which I am sorting by full name and I apologize if this is a 101 question as I am still new to C++ and come from a C# background.
My question is why does the comparer work when its defined inline to the object being used but throw a compile error when you try and pass in a comparer that resides inside a class.
The PersonExample class does not have a compare_fullName function.
Some other things:
There is no need to use this-> like you do, a class has direct access to it's members. Only use it if you need to disambiguate.
Pass std::string or any container by const reference, and use a member initialization list in the constructor:
1 2 3 4 5 6 7 8 9 10 11
PersonExample::PersonExample(const std::string& LastName,
const std::string& MiddleName ,
const std::string& FirstName)
: // colon introduces member init list
firstName (FirstName), // direct initialization, use brace initialization for numbers to prevent narrowing
middleName (MiddleName),
lastName (LastName)
{
// if required do validation here
}
Thank you for the explanation and reference links. The reason I am using the list over the vector is just to basically get a better understanding of them and how I can use them. I come from C# and we don't have a vector concept and all generics are based really off lists. I apologize I forgot to include the code I was using for the PersonExample comparer, I have included it below.
passing the const version simply prevents manipulation of the original variable is that correct?
I come from C# and we don't have a vector concept and all generics are based really off lists.
In C++ std::vector is a really good container, I have been surprised a number of times where experts here have explained & shown how efficient it is.
passing the const version simply prevents manipulation of the original variable is that correct?
Yes, and applying it to a member functions means it can't alter the state of the class object. That is, it can't alter the value of any of the member variables. This is called const correctness and is a very good thing. So you could do this with your compare functions for example:
So if I simply called compare without specifying the custom comparer method how will it know which of the getter methods I wish to do the compare on? If this time I wanted to compare and sort via lastname but next time I want to sort on Firstname, etc?
Originally I was using the const in my comparer method but when I attempted to do first.getLastName().length() it would tell me length() did not exist. So, in order to get back the length method I removed the const.
So if I simply called compare without specifying the custom comparer method how will it know which of the getter methods I wish to do the compare on? If this time I wanted to compare and sort via lastname but next time I want to sort on Firstname, etc?
You are right, I realized that after I posted my reply. I applied the strikeout to that part.
Originally I was using the const in my comparer method but when I attempted to do first.getLastName().length() it would tell me length() did not exist. So, in order to get back the length method I removed the const.
Sorry I must be a bit tired :+( I forgot to say that const functions can only call other const functions (makes sense really) , so all of your get functions should be const too.
And yes, first.getLastName().length() doesn't exist, a function cannot contain another function. Any way just use lexicographical_compare. If you can't use this algorithm for the assignment, then assign the value of the lengths to different variables. It better to assign values outside the loop so those get functions aren't called repeatedly. You only need to loop on the shorter one: if it gets to the end of that, then the shorter one is less than.
This bit could be improved: there are only 2 ways it can go, no need to repeat the logic in reverse.
1 2
if (tolower(first.getLastName()[i])<tolower(second.getLastName()[i])) returntrue;
elseif (tolower(first.getLastName()[i])>tolower(second.getLastName()[i])) returnfalse;
Edit: Actually that part could use the ternary operator on 1 line of code
> I come from C# and we don't have a vector concept and all generics are based really off lists.
CLRs System.Collections.Generic.List<T> is similar to std::vector<T> where the type T is a CTS value type System.Collections.Generic.List<T> is similar to std::vector< std::shared_ptr<T> > where the type T is a CTS reference type
CLRs System.Collections.Generic.LinkedList<T> is similar to std::list<T> where the type T is CTS a value type System.Collections.Generic.LinkedList<T> is similar to std::list< std::shared_ptr<T> > where the type T is a CTS reference type
Even if the syntax looks somewhat similar, there are many fundamental differences between C# and C++. This may give you an idea of some of them: