0

I implemented a public member method in a class, which uses std::sort(). The function sort on the other hand takes a compare function (let's call it helpSort() ) as third argument.

Now the question is, where or how do I have to declare and implement helpSort() so that:

  1. it will work.
  2. encapsulation is ensured.

What is considered here as good design?

Declaring it plain inside the class does not work.

fotinsky
  • 862
  • 2
  • 10
  • 24

2 Answers2

1

I think the best solution would be to implement

bool helpSort(const T& a, const T& b)

as a free function, and sort objects based on their publicly observable properties. If there are const accessor member functions you need to add, and they make sense as part of the observable properties of the class, you could add those member functions in order to accomplish this.

As an example, if you could implement your sort function as

bool helpSort(const T& a, const T& b) { return a.property() < b.property(); }

where property() is a public function, this will make the helpSort function work, even as the implementation of T changes, as long as the public interface/contract for class T remains the same. That is, your helpSort function will continue to compile and remain meaningful, as long as the meaning of property() is not changed, even as your implementation of class T evolves.

If the number of accessors you would need becomes unreasonable, I think it's reasonable to declare helpSort a friend function. I personally think friend functions taking const instances as parameters are much less dangerous than friend class cases (which I avoid at all costs). In principle, such a function could be implemented in terms of public accessors, but perhaps it would be inconvenient or unreasonable.

If you have heard advice to "never have friends", it's possible someone had bad experiences with friend classes, which really can rupture encapsulation.

Finally, you can declare a static member function within your class as a comparison function. I think it's pretty similar to a friend free function. The one advantage to a free function is that you know, structurally, that it cannot alter the state of the object by modifying some static variable within the class.

You can read more about the differences at these links:

Static member functions

What kind of member access do friend and static member functions have?

Community
  • 1
  • 1
NicholasM
  • 3,771
  • 1
  • 16
  • 37
  • Right now I have declared it in the same .hpp file as the class, but not inside the class (implementation in the .cpp), and it works. I am still not sure if this is good design, because the sort criterion is only for this one member method. – fotinsky Nov 06 '13 at 04:59
  • Sorry for the edit as I thought of how to explain in more detail. How would you characterize your current solution: a free function, or a free function that is a `friend function`? – NicholasM Nov 06 '13 at 05:11
  • Just a help function for this one particular method. Will not be used somewhere else. – fotinsky Nov 06 '13 at 05:17
  • I think placing it in the same header/source file is fine. Do you have a `friend` declaration inside the class? Does it act by const reference? If you want, you could post the declaration (not implementation) of the function, to see if anyone has specific feedback based on that. – NicholasM Nov 06 '13 at 05:22
  • WRT the encapsulation, if the class is in it's own namespace, having helpSort() in that namespace as well will help with the encapsulation (since I think you said this was to be public). OTOH, if this helper is only used internally and you don't want it exposed, it can reside in the implementation file instead. – rholmes Jan 17 '14 at 03:12
1

Declaring it plain inside the class does not work.

Why not? You can write helpSort() as a static private member function and pass that as the comparator and it should work just fine. Without knowing more about what you're trying to do, that would be my preferred solution.

Tristan Brindle
  • 15,036
  • 2
  • 31
  • 79