So, I've created a class and then construct two separate instances of that class:
disc discOne; // Construct objects
disc discTwo;
The declaration of the class is done separately through a header file:
class disc
{
public:
disc();
~disc();
void changeRadius(short);
void throwDisc(short, short);
void printLocation() const;
void printInfo() const;
private:
short radius;
short xlocation;
short ylocation;
};
I can use the printInfo() and changeRadius() functions for example, but how can I compare (for example) the radius between these two objects? I want to do something more complex than this, but if I understand the basics I want to try and figure it out.
The problem I'm running in to is that I've used structures in the past, which (if this was the case), I would simply go:
discOne.radius > discTwo.radius
Or something similar. But, that syntax for classes calls a function tied to that class. Sorry for the rambling, but I'm having trouble articulating it - probably why I've struggled to find any guidance through my own searches on the internet.
Three ways:
Use a getter method getRadius() const {return radius;}
and just compare as you always did.
Use overload for operator< and operator> if you want to compare two objects directly (but this doesn't seems the right case.
Declare a friend function bool compareRadius(const Disc& discOne, const Disc& discTwo) to perform the comparison without involving directly the objects.
Of course the simpliest way is the first. I just showed some other option you could consider for similar problems.
Edit: Answer #3 is based on Scott Meyer's Effective C++, item 23 (though it specifies non-friend).
You could add a "getter" to your class (like short getRadius() const) through which you can obtain a value to compare: discOne.getRadius() < discTwo.getRadius().
Alternatively you could add a operator< overload to disc itself, and have it perform the comparison between radii. However, this only makes sense if the radius is the only property of the disc (which it isn't — you have location also), and if comparing radii is equivalent to comparing discs (and I'm not convinced that this would be logical).
Beyond that there are all sorts of clumsy solutions, like adding a bool radiusIsLesserThatThisOtherDiscsRadius(const disc& otherDisc) const member function.
But, that syntax for classes calls a function tied to that class
Actually, that's not true; C++ does not have "structures", so struct introduces a class too, and discOne.radius > discTwo.radius would have worked just fine here if radius were not a private data member. But it being a private data member is appropriate.
struct disc
{
public:
disc();
~disc();
void changeRadius(short);
void throwDisc(short, short);
void printLocation() const;
void printInfo() const;
private:
short radius;
short xlocation;
short ylocation;
};
// ^ Exactly the same thing; your approach still won't work, for the same reason
Simple solution to overload the > operator on objects like below to compare radius of two objects of the class.
discOne > discTwo;
you can overload > according to your requirement, Here is the simple one
bool disc :: operator > (disc my_disc)
{
if(radius > my_disc.radius)
return true;
else
return false;
}
Above one is one of the solution to solve your problem. There are other ways by which you can compare two objects as suggested by others. Use separate member function( or friend function) to do the same task.
Related
Let say we have some classes which have relations between them. AS an example geometry or math libraries have Vector3, Matrix4, Plane3..etc. There are lots of intersection test methods between them. For example testing intersection between Plane3 and Vector3; if Vector3(as point) on plane, out of plane back and out of plane front...etc.
So the intersection test method can be written on both Vector3 and Plane3 class. But this causes a litlle complication and repeating of hard coding. So is there any advice for this situation.
Implement the method on one class which has more meaning to has it, specically on Plane3 because it is used more for intersections, its aim is, intersection test and this kind of things.
Implement on both classes.
Implement in a utility class as a static method.
Other
The first case can be good but sometimes the situation is not clear as it says. And the second requires more repeated code specialy for lots of classes with lots of methods causes cartesian multiplication of code increasing. Third one can be good but sometimes it cannot access private or protected methods of classes (if not implemented as friend) and I generaly don't know how to categorize utility classes and it will be more diffucult for user to know where is the method he/she is looking for. So is there any aproaches for this situation?
Edit: More detailed examples.
class A {}
class B {}
class C {}
First:
bool A::IsIntersecting(const B& b) const;
bool A::IsIntersecting(const C& c) const;
bool B::IsIntersecting(const C& c) const;
Second:
bool A::IsIntersecting(const B& b) const;
bool A::IsIntersecting(const C& c) const;
bool B::IsIntersecting(const A& a) const;
bool B::IsIntersecting(const C& c) const;
bool C::IsIntersecting(const A& a) const;
bool C::IsIntersecting(const B& b) const;
Third:
bool IntersectUtility::IsIntersecting(const A &a, const B &b);
bool IntersectUtility::IsIntersecting(const A &a, const C &c);
bool IntersectUtility::IsIntersecting(const B &b, const C &c);
If you have a function that operates across multiple classes, you could consider making it a free-standing function. Remember: not every function needs to be associated with a class (unless you are using Java or C#). Thus, you could have something like:
bool intersects(const T1 &a, const T2 &b);
The next thing to consider is what relations are possible and make sense (e.g. it does not make sense to ask if a vector intersects a matrix). This will tell you what combinations of classes should be used with the method.
Next, consider equivalences within the method. If A op B == B op A, then you can write:
inline bool intersects(const Vector3 &a, const Plane3 &b)
{
return intersects(b, a);
}
This is used when implementing the relational operators -- you can implement != in terms of == and >, >=, <= in terms of <.
This also applies for compositions (e.g. calling intersects on the x and y coordinates of a Point2D object).
If you are writing a library, you should write the most common/useful combinations first and aim for a comprehensive set (where they make sense). If you are writing an application, you should focus on providing what is needed.
Implement the method on one class which has more meaning to has it, specically on Plane3 because it is used more for intersections, its aim is, intersection test and this kind of things.
This solution "smells" to me, for several reasons. The biggest problem I see is that it would be very confusing when consumers are trying to figure out where the intersectionTest function for a particular pair of geometric objects is located. eg is it in Line or Point? What about testing if the Line intersects a Plane? I can see a temptation to pick an arbitrary rule, like higher-dimensional objects contain the functions corresponding to the lower-dimensional, but then you run into the same problem when you're testing objects of the same dimensions.
Implement on both classes.
This is too much duplicate code. However, you might be able to get away with creating a base implementation for 1D, 2D, 3D, etc that is able to do the majority of the work. This would obviously utilize inheritance, and you said that you didn't want to do that.
Implement in a utility class as a static method.
The reason that this doesn't have an obvious solution is that the intersection of the two (or more, which it doesn't seem like you want to consider) of these objects doesn't really belong to either of them. It belongs to the "space" they're in. So my suggestion would be to think less about one object intersecting another and instead build a solution based on their position in "space", whether that's 1D-space, 2d, etc. At the end of the day, whether you implement this as bare or static functions, a base class, or a container that holds your objects is up to you.
I would suggest making isIntersecting a set of non-member functions in the same namespace as A, B and C:
namespace X {
class A { };
class B { };
class C { };
bool isIntersecting(const A&, const B&);
bool isIntersecting(const A&, const C&);
bool isIntersecting(const B&, const C&);
}
And only make them friend if you have to.
Class classname
{
int member1;
int member2;
...
int membern;
public:
void setmember1(int);
void setmember2(int);
...
void setmembern(int);
void getmember1(int);
void getmember2(int);
...
void getmembern(int);
}
I know that I can define 2n class functions to get and set n specified member values in-place for the declarations above.
However, this seems needlessly tedious when n is large. Is there a good way to define one class function that takes an extra argument to set/get any member of the class?
EDIT:
Syntax errors aside, my rationale for large n is to preserve the scientific framework behind the class. For example, say the class is enzyme. So I'd prefer to keep its properties in the same place and not index by number unless absolutely necessary.
Set/get functions are public because they're called in a different class (that sets up a GUI).
And, no, not all the members are ints. I copy-pastaed for the sake of simplicity.
In real code you should not have classes with many data members, and certainly not individually settable and gettable ones.
You could achieve what you are asking for using an array:
class classname
{
public:
setMemberDangerously(size_t index, int value) { data[index] = value; }
setMember(size_t index, int value)
{
if (! index < size) throw std::out_of_range("Index out of bounds");
data[index] = value;
}
private:
int data[N];
};
But now your class looks like a collection, in which case you might as well use a standard library container.
Either:
Write a script to generate the methods
Put all those integers into an array and use one get/set with an index
EDIT
Besides your get should be
int getX() const;
EDIT
Thought of another two possibilities
Overload the [] operator
Inherit from std::vector
You can invent any tools to make your bad-designed classes "almost manageable". If it's hard to write getters/setters, don't do this. Your class must be refactored.
General solution here is to avoid big values of n
Design your classes to preserve single responsibility principle. Avoid god-classes.
I am no fun of setters/getters, although they are quite common in applications like a GUI. Anyhow, I have a generic solution that does require a library and is probably an overkill for this problem. Assume you have the following class
class A
{
char member1;
int member2;
double membern;
public:
void set_member1(char c) { member1 = c; }
void set_member2(int i) { member2 = i; }
void set_membern(double d) { membern = d; }
char get_member1() { return member1; }
int get_member2() { return member2; }
double get_membern() { return membern; }
};
You can then write
auto val = _('c', 42, 3.14);
auto set = _(&A::set_member1, &A::set_member2, &A::set_membern);
auto get = _(&A::get_member1, &A::get_member2, &A::get_membern);
A a;
(a ->* set)(val);
cout << (a ->* get)() << endl;
which prints
(c, 42, 3.14)
That is, you are working with tuples. Syntax _(...) represents a tuple; val is a tuple of values (possibly of different types) and set/get are tuples of pointers to members. Operator ->* in the syntax given above allows calling multiple member functions on a single object with multiple arguments, one argument per function. The result of the call to get is again a tuple of values.
For all this to work, you need library ivl that I am currently developing. The syntax above is just a small sample; the library is much more flexible, allowing to define functions or operators for scalars and then call them on tuples or arrays, in any combination. All C++ operators are overloaded to allow this kind of "vectorization". Operator ->* can also work with function objects apart from pointers to members, so that calls are inlined. It also allows the alternative syntax
a ->* set._(val);
cout << a ->* get._() << endl;
so that member functions bind with arguments first, before being applied to the object(s). Member functions can have as many arguments (of any type) as you like, but all should have the same number of arguments in a single call.
You touched an old problem with C++, which is very limited reflection functionality in the language. The discussion below is worth to look at in case you came from a language with reflection:
How can I add reflection to a C++ application?
As for a practical advice, all other answers given here make perfect sense.
I have a class Feature with a pure virtual method.
class Feature {
public:
virtual ~Feature() {}
virtual const float getValue(const vector<int>& v) const = 0;
};
This class is implemented by several classes, for example FeatureA and FeatureB.
A separate class Computer (simplified) uses the getValue method to do some computation.
class Computer {
public:
const float compute(const vector<Feature*>& features, const vector<int>& v) {
float res = 0;
for (int i = 0; i < features.size(); ++i) {
res += features[i]->getValue(v);
}
return res;
}
};
Now, I am would like to implement FeatureC but I realize that I need additional information in the getValue method. The method in FeatureC looks like
const float getValue(const vector<int>& v, const vector<int>& additionalInfo) const;
I can of course modify the signature of getValue in Feature, FeatureA, FeatureB to take additionalInfo as a parameter and also add additionalInfo as a parameter in the compute method. But then I may have to modify all those signatures again later if I want to implement FeatureD that needs even more additional info. I wonder if there is a more elegant solution to this or if there is a known design pattern that you can point me to for further reading.
You have at least two options:
Instead of passing the single vector to getValue(), pass a struct. In this struct you can put the vector today, and more data tomorrow. Of course, if some concrete runs of your program don't need the extra fields, the need to compute them might be wasteful. But it will impose no performance penalty if you always need to compute all the data anyway (i.e. if there will always be one FeatureC).
Pass to getValue() a reference to an object having methods to get the necessary data. This object could be the Computer itself, or some simpler proxy. Then the getValue() implementations can request exactly what they need, and it can be lazily computed. The laziness will eliminate wasted computations in some cases, but the overall structure of doing it this way will impose some small constant overhead due to having to call (possibly virtual) functions to get the various data.
Requiring the user of your Feature class hierarchy to call different methods based on class defeats polymorphism. Once you start doing dynamic_cast<>() you know you should be rethinking your design.
If a subclass requires information that it can only get from its caller, you should change the getValue() method to take an additionalInfo argument, and simply ignore that information in classes where it doesn't matter.
If FeatureC can get additionalInfo by calling another class or function, that's usually a better approach, as it limits the number of classes that need to know about it. Perhaps the data is available from an object which FeatureC is given access to via its constructor, or from a singleton object, or it can be calculated by calling a function. Finding the best approach requires a bit more knowledge about the case.
This problem is addressed in item 39 of C++ Coding Standards (Sutter, Alexandrescu), which is titled "Consider making virtual functions nonpublic, and public functions nonvirtual."
In particular, one of the motivations for following the Non-Virtual-Interface design pattern (this is what the item is all about) is stated as
Each interface can take its natural shape: When we separate the public interface
from the customization interface, each can easily take the form it naturally
wants to take instead of trying to find a compromise that forces them to look
identical. Often, the two interfaces want different numbers of functions and/or
different parameters; [...]
This is particularly useful
In base classes with a high cost of change
Another design pattern which is very useful in this case is the Visitor pattern. As for the NVI it applies when base classes (as well as the whole hierarchy) have a high cost of change. You can find plenty of discussion about this design pattern, I suggest you to read the related chapter in Modern C++ (Alexandrescu), which (on the side) gives you a great insight on how to use the (very easy to use) Visitor facilities in loki
I suggest for you to read all of this material and then edit the question so that we can give you a better answer. We can come up with all sort of solutions (e.g. use an additional method which gives the class the additional parameters, if needed) which might well not suit your case.
Try to address the following questions:
would a template-based solution fit the problem?
would it be feasible to add a new layer of indirection when calling the function?
would a "push argument"-"push argument"-...-"push argument"-"call function" method be of help? (this might seem very odd at first, but
think to something like "cout << arg << arg << arg << endl", where
"endl" is the "call function")
how do you intend to distinguish how to call the function in Computer::compute?
Now that we had some "theory", let's aim for the practice using the Visitor pattern:
#include <iostream>
using namespace std;
class FeatureA;
class FeatureB;
class Computer{
public:
int visitA(FeatureA& f);
int visitB(FeatureB& f);
};
class Feature {
public:
virtual ~Feature() {}
virtual int accept(Computer&) = 0;
};
class FeatureA{
public:
int accept(Computer& c){
return c.visitA(*this);
}
int compute(int a){
return a+1;
}
};
class FeatureB{
public:
int accept(Computer& c){
return c.visitB(*this);
}
int compute(int a, int b){
return a+b;
}
};
int Computer::visitA(FeatureA& f){
return f.compute(1);
}
int Computer::visitB(FeatureB& f){
return f.compute(1, 2);
}
int main()
{
FeatureA a;
FeatureB b;
Computer c;
cout << a.accept(c) << '\t' << b.accept(c) << endl;
}
You can try this code here.
This is a rough implementation of the Visitor pattern which, as you can see, solves your problem. I strongly advice you not to try to implement it this way, there are obvious dependency problems which can be solved by means of a refinement called the Acyclic Visitor. It is already implemented in Loki, so there is no need to worry about implementing it.
Apart from implementation, as you can see you are not relying on type switches (which, as somebody else pointed out, you should avoid whenever possible) and you are not requiring the classes to have any particular interface (e.g. one argument for the compute function). Moreover, if the visitor class is a hierarchy (make Computer a base class in the example), you won't need to add any new function to the hierarchy when you want to add functionalities of this sort.
If you don't like the visitA, visitB, ... "pattern", worry not: this is just a trivial implementation and you don't need that. Basically, in a real implementation you use template specialization of a visit function.
Hope this helped, I had put a lot of effort into it :)
Virtual functions, to work correctly, needs to have exactly the same "signature" (same parameters and same return type). Otherwise, you just get a "new member function", which isn't what you want.
The real question here is "how does the calling code know it needs the extra information".
You can solve this in a few different ways - the first one is to always pass in const vector <int>& additionalInfo, whether it's needed or not.
If that's not possible, because there isn't any additionalInfo except for in the case of FeatureC, you could have an "optional" parameter - which means use a pointer to vector (vector<int>* additionalInfo), which is NULL when the value is not available.
Of course if additionalInfo is a value that is something that can be stored in the FeatureC class, then that would also work.
Another option is to extend the base class Feature to have two more options:
class Feature {
public:
virtual ~Feature() {}
virtual const float getValue(const vector<int>& v) const = 0;
virtual const float getValue(const vector<int>& v, const vector<int>& additionalInfo) { return -1.0; };
virtual bool useAdditionalInfo() { return false; }
};
and then make your loop something like this:
for (int i = 0; i < features.size(); ++i) {
if (features[i]->useAdditionalInfo())
{
res += features[i]->getValue(v, additionalInfo);
}
else
{
res += features[i]->getValue(v);
}
}
I have a class:
class A
{
public:
virtual void func() {…}
virtual void func2() {…}
};
And some derived classes from this one, lets say B,C,D... In 95 % of the cases, i want to go through all objects and call func or func2(), so therefore i have them in a vector, like:
std::vector<std::shared_ptr<A> > myVec;
…
for (auto it = myVec.begin(); it != myVec.end(); ++it)
(*it).func();
However, in the rest 5 % of the cases i want to do something different to the classes depending on their subclass. And I mean totally different, like calling functions that takes other parameters or not calling functions at all for some subclasses. I have thought of some options to solve this, none of which I really like:
Use dynamic_cast to analyze subclass. Not good, too slow as I make calls very often and on limited hardware
Use a flag in each subclass, like an enum {IS_SUBCLASS_B, IS_SUBCLASS_C}. Not good as it doesnt feel OO.
Also put the classes in other vectors, each for their specific task. This doesnt feel really OO either, but maybe I'm wrong here. Like:
std::vector<std::shared_ptr<B> > vecForDoingSpecificOperation;
std::vector<std::shared_ptr<C> > vecForDoingAnotherSpecificOperation;
So, can someone suggest a style/pattern that achieves what I want?
Someone intelligent (unfortunately I forgot who) once said about OOP in C++: The only reason for switch-ing over types (which is what all your suggestions propose) is fear of virtual functions. (That's para-paraphrasing.) Add virtual functions to your base class which derived classes can override, and you're set.
Now, I know there are cases where this is hard or unwieldy. For that we have the visitor pattern.
There's cases where one is better, and cases where the other is. Usually, the rule of thumb goes like this:
If you have a rather fixed set of operations, but keep adding types, use virtual functions.
Operations are hard to add to/remove from a big inheritance hierarchy, but new types are easy to add by simply having them override the appropriate virtual functions.
If you have a rather fixed set of types, but keep adding operations, use the visitor pattern.
Adding new types to a large set of visitors is a serious pain in the neck, but adding a new visitor to a fixed set of types is easy.
(If both change, you're doomed either way.)
According to your comments, what you have stumbled upon is known (dubiously) as the Expression Problem, as expressed by Philip Wadler:
The Expression Problem is a new name for an old problem. The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g., no casts).
That is, extending both "vertically" (adding types to the hierarchy) and "horizontally" (adding functions to be overriden to the base class) is hard on the programmer.
There was a long (as always) discussion about it on Reddit in which I proposed a solution in C++.
It is a bridge between OO (great at adding new types) and generic programming (great at adding new functions). The idea is to have a hierachy of pure interfaces and a set of non-polymorphic types. Free-functions are defined on the concrete types as needed, and the bridge with the pure interfaces is brought by a single template class for each interface (supplemented by a template function for automatic deduction).
I have found a single limitation to date: if a function returns a Base interface, it may have been generated as-is, even though the actual type wrapped supports more operations, now. This is typical of a modular design (the new functions were not available at the call site). I think it illustrates a clean design, however I understand one could want to "recast" it to a more verbose interface. Go can, with language support (basically, runtime introspection of the available methods). I don't want to code this in C++.
As already explained myself on reddit... I'll just reproduce and tweak the code I already submitted there.
So, let's start with 2 types and a single operation.
struct Square { double side; };
double area(Square const s);
struct Circle { double radius; };
double area(Circle const c);
Now, let's make a Shape interface:
class Shape {
public:
virtual ~Shape();
virtual double area() const = 0;
protected:
Shape(Shape const&) {}
Shape& operator=(Shape const&) { return *this; }
};
typedef std::unique_ptr<Shape> ShapePtr;
template <typename T>
class ShapeT: public Shape {
public:
explicit ShapeT(T const t): _shape(t) {}
virtual double area() const { return area(_shape); }
private:
T _shape;
};
template <typename T>
ShapePtr newShape(T t) { return ShapePtr(new ShapeT<T>(t)); }
Okay, C++ is verbose. Let's check the use immediately:
double totalArea(std::vector<ShapePtr> const& shapes) {
double total = 0.0;
for (ShapePtr const& s: shapes) { total += s->area(); }
return total;
}
int main() {
std::vector<ShapePtr> shapes{ new_shape<Square>({5.0}), new_shape<Circle>({3.0}) };
std::cout << totalArea(shapes) << "\n";
}
So, first exercise, let's add a shape (yep, it's all):
struct Rectangle { double length, height; };
double area(Rectangle const r);
Okay, so far so good, let's add a new function. We have two options.
The first is to modify Shape if it is in our power. This is source compatible, but not binary compatible.
// 1. We need to extend Shape:
virtual double perimeter() const = 0
// 2. And its adapter: ShapeT
virtual double perimeter() const { return perimeter(_shape); }
// 3. And provide the method for each Shape (obviously)
double perimeter(Square const s);
double perimeter(Circle const c);
double perimeter(Rectangle const r);
It may seem that we fall into the Expression Problem here, but we don't. We needed to add the perimeter for each (already known) class because there is no way to automatically infer it; however it did not require editing each class either!
Therefore, the combination of External Interface and free functions let us neatly (well, it is C++...) sidestep the issue.
sodraz noticed in comments that the addition of a function touched the original interface which may need to be frozen (provided by a 3rd party, or for binary compatibility issues).
The second options therefore is not intrusive, at the cost of being slightly more verbose:
class ExtendedShape: public Shape {
public:
virtual double perimeter() const = 0;
protected:
ExtendedShape(ExtendedShape const&) {}
ExtendedShape& operator=(ExtendedShape const&) { return *this; }
};
typedef std::unique_ptr<ExtendedShape> ExtendedShapePtr;
template <typename T>
class ExtendedShapeT: public ExtendedShape {
public:
virtual double area() const { return area(_data); }
virtual double perimeter() const { return perimeter(_data); }
private:
T _data;
};
template <typename T>
ExtendedShapePtr newExtendedShape(T t) { return ExtendedShapePtr(new ExtendedShapeT<T>(t)); }
And then, define the perimeter function for all those Shape we would like to use with the ExtendedShape.
The old code, compiled to work against Shape, still works. It does not need the new function anyway.
The new code can make use of the new functionality, and still interface painlessly with the old code. (*)
There is only one slight issue, if the old code return a ShapePtr, we do not know whether the shape actually has a perimeter function (note: if the pointer is generated internally, it has not been generated with the newExtendedShape mechanism). This is the limitation of the design mentioned at the beginning. Oops :)
(*) Note: painlessly implies that you know who the owner is. A std::unique_ptr<Derived>& and a std::unique_ptr<Base>& are not compatible, however a std::unique_ptr<Base> can be build from a std::unique_ptr<Derived> and a Base* from a Derived* so make sure your functions are clean ownership-wise and you're golden.
Suppose we have an object which represent a box.
class Box {
public:
int length;
int width;
int height;
Box(int l, int w, int h);
~Box();
int area(const int l, const int w) const;
int volume(const int l, const int w, const int h) const;
};
Now lets say in another class, in another file, we have an std::list<Box> that contains n boxes. We want to display a print out of these boxes in different ways.
First we want to print them out in order of increasing size by their lengths.
Then we want to print them out in order of increasing size by their widths.
We don't care about their heights right now, but maybe later we will.
Now std::list has a member function sort() that takes a comparison function as an argument. How can we alter the above Box class so that we can call sort() on our list with different comparison functions?
More specifically, can we define three different functions inside the box class and simply pass them to list.sort()? Is it better to define the comparison functions globally outside of the class Intuitively, tying them to the class seems better but why would this not be the case? Overall, what is the "best" way to achieve this?
If you really want to implement the three different comparison
operations as members you can do something like this:
struct Box {
int x, y, length;
bool less_by_x(const Box& other) { return this.x < other.x; }
bool less_by_y(const Box& other) { return this.y < other.y; }
bool less_by_length(const Box& other) { return this.y < other.y; }
};
and use them like this:
#include <functional>
// you probably shouldn't be using a list anyway
std::list<Box> l;
l.sort(std::mem_fun_ref(&Box::less_by_x));
mem_fun_ref returns an binary function object that takes a reference to the class of which the function is a member and all the rest of the arguments (only in C++11, this is limited to binary functions in C++03) of the member functions.
Although it seems much more reasonable to implement the comparison
operations as free functions.
You have to provide a comparator function (or a function object). For example:
bool my_sort_function (const Box& box1, const Box& box2)
{
// use some criteria and return a boolean (true if box1 goes before box2)
// ...
}
Then invoke the sort () method in the following way:
my_list.sort (my_sort_function);
std::list::sort() accepts a comparison function object, which lets you define custom sort criteria. This can be a normal function (free function or static member) or an instance of a class with a compatible operator(). See some documentation for details and an example.
The various sorting functions in the standard C++ library take comparision objects. These may contain whatever data they need. The key requirements they have is that they are copyable and that their function call operator yields a strickt weak order when applied to objects of their argument type. It is easy to create a comparison object which e.g. stores a pointer to member function used to map an object to an attribute, especially if all the attributes have the same type (if the attributes have different types things are bit more interesting). With this it is rather straight forward to sort the same list into different orders.
The best way to do this is to implement a comparison function for each parameter and pass that to sort when calling the sort.
That function boolean comparison(Box a, Box b) should be equivalent to a < b, that is, it is true if a comes before b when sorting by that parameter.
If you want to pass member functions as parameters then your best option is to use boost::mem_fn