Function objects are simple but don’t let that fool you. You can use them in clever solutions.
How do you actually use functors?
A really great example is in the C++ standard library collection classes. Some of the collection classes support sorting. In fact, some of them require sorting. Now you might think, okay, what’s so special about that? And if all you have is a collection of numeric types or maybe a collection of dates, then, yes, sorting is fairly easy. But wait a moment. Which way? Should your collection hold 1, 2, 3, or should it hold 3, 2, 1? Even numeric values have a little extra functionality.
What about custom classes with several member data fields? Should they all be looked at? In what order? Or do you let the user change the sort order by clicking column headers? What if you want to sort by one property and then another? Let’s say you have a list of items for sale. Maybe the user wants to see them sorted by price. That’s good but what if a whole bunch of them all cost the same? Should similar priced items then be shown in a random order? Probably not. It makes sense to sort the items by price since that’s what the user selected but then sort them again by name for items of the same price.
Well, the container classes have absolutely no idea how to do all this. You can write your own function object that knows exactly how to work with whatever properties you need. But using functors, gives you more benefits than just this.
One of the template parameters that is sometimes available depending on the collection is a sort operation. Let’s say you want to create a set to hold integers. If you just write set
Less is a predefined functor. It’s a template class that uses operator less than on two values that match the template type. What if you want to put instances of your own custom class into a set. If you don’t specify otherwise, you’ll get less as the sorting functor. And this uses operator less than. It’ll all work just fine as long as your class implements operator less than or if your class instances can be automatically converted to some type that does implement operator less than. This is not always a good thing to provide.
When you’re designing your own class, you really should implement operator less than if it is obvious and expected what the outcome will be. If your class wraps up some numeric value in an interesting way, then it probably makes sense and would be expected to provide an operator less than.
But what if your class represents inventory items? It’s not so clear anymore what property to use when comparing them. Should you use size? How about weight? Cost? Color? We’re not really talking about displaying item though. We just want to put these things in a collection. And for that, we need something to sort by. You may want to use an identity field for this. So you create a functor that knows how to sort your inventory items by an identity field that the user will never see. You can then provide that functor to your set collection to use for the sorting.
And this goes to one of the biggest strengths of functors. They’re types. Because you used your custom functor when creating your set, it becomes part of the type of the set too. This means that the compiler can help you if you ever try to mix sets created with different functors. They’ll be different types and you’ll get compile errors.