C ++ operator overload, understanding google style guide

I am following a book to learn C ++ (from python background). I wrote this that works:

class CatalogueItem { public: CatalogueItem(); CatalogueItem(int item_code, const string &name, const string &description); ~CatalogueItem() {}; bool operator< (const CatalogueItem &other) const; ... private: ... }; ... list<CatalogueItem> my_list; // this is just me playing around CatalogueItem items[2]; items[0] = CatalogueItem(4, string("box"), string("it a box")); items[1] = CatalogueItem(3, string("cat"), string("it a cat")); my_list.push_back(items[0]); my_list.push_back(items[1]); my_list.sort(); 

The part I'm trying to use uses the <operator to enable sorting of the list.

It all seems good, but http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Operator_Overloading seems to suggest avoiding it, which is exactly what the book says! ("In particular, do not overload operator == or operator <just so that your class can be used as a key in the STL container, instead you should create types of equality and comparison functions when declaring the container.")

I understand that “create equality and comparison types” means creating comparison functions, for example, below:

 bool my_comparison_function(const CatalogueItem &a, const CatalogueItem &b) { // my comparison code here } 

Is this what the style guide refers to?

Does anyone have the opportunity to indicate which method is more "correct"?

J

+4
source share
3 answers

The type of functor will be more like this:

 struct CatalogueItemLessThan { bool operator()(const CatalogueItem &a, const CatalogueItem &b) { } }; 

Then use will look like this:

 list<CatalogueItem> my_list; // this is just me playing around CatalogueItem items[2]; items[0] = CatalogueItem(4, string("box"), string("it a box")); items[1] = CatalogueItem(3, string("cat"), string("it a cat")); my_list.push_back(items[0]); my_list.push_back(items[1]); my_list.sort(CatalogueItemLessThan()); 

The main advantage of this is that you can separate the sorting from the object itself. Now you can provide as many sort types as you want and use them in different places. (For example, a string can be sorted lexically or case-insensitively, or naturally . "

The advantage of using a functor as opposed to a free function is that you can pass parameters to a comparison to change how the functor functions.

In general, the Google style guide is actually not the best style guide (IMHO, especially their exclusion from exceptions, but that's another discussion). If the object has an obvious sort order, I often add operator< by default. If later, there are additional sort orders that I want to add, then I add free functions. If at a later time I need to add parameters to the sort order, I will make them into functors. It makes no sense to add complexity before you need it.

+10
source

What Google is trying to tell you is as follows.

As you know, you can overload one and only one operator '<' for a given type. Let them say it works for you. But imagine that in the future you may need to sort objects of one type according to some other comparison criterion. How do you do this? The only available version of '<' is already accepted.

Of course, you can do this by writing a new named function / comparison functor (not the "<" operator) and explicitly passing it to the sorting algorithm. You can write another 2, 5, 10 of them. You can write as much as you want. This will work. However, at this point in your code there will be obvious asymmetries. One comparison function is implemented as the "operator <". The rest are like different named functions / functors. Is there a good reason for this asymmetry?

Well, maybe. If you have a very well-defined and obvious method of natural sorting that applies to your type, it makes very good sense to implement it as operator '<'. This will be the main method of comparison. And other, auxiliary, less "natural" comparison methods can and should be implemented as named functions. This is normal.

However, what if you do not have such an obvious candidate for a “natural” comparison? In this case, preference is given to one method over another and “wasting” the value of “<operator on an arbitrarily chosen one is not a good idea. In this case, it is recommended to leave the '<' symbol and stick to name functions / functors.

In other words, by overloading '<' you create a “favorite” comparison for this type. If this is what you really want, go ahead and do it. But keep in mind that in many cases creating an artificial and arbitrary “favorite” is not a good idea. Do not rush the process of choosing this favorite. Do not take '<' too early.

+8
source

A functor type is a C ++ type (class or structure) that overloads the () operator, so that type instances behave like a function. This is similar to a class that implements __call__() in Python.

Some types of STL collections, such as std::map , require the key_compare functor to arrange keys in firewall structures and thus provide quick access. The default is std::less , which uses operator< to compare values. Therefore, this operator is often provided so that user classes can act as keys in std::map (and the like).

Google is obviously discouraged by this in favor of providing your own comparison functor. Thus, instead of implementing operator< you can do the following:

 struct my_compare { bool operator ()(const CatalogueItem& lhs, const CatalogueItem& rhs) { ... } }; 

If you must access private members to implement this, declare functor as a friend your class.

+1
source

All Articles