Search code examples
c++c++11operator-overloadinga-star

Can overloading shift operators for things other than I/O be a good design?


I am implementing the Open List (OL) class for the A* search algorithm. The OL is basically a specialized priority queue of search nodes. It is common to see a notation like this in the pseudo-code describing the A* algorithm:

    successorNode -> OL // put the successor node into OL
    ...
    curNode <- OL // get the best node from OL and store it in curNode

Three questions:

  1. Would it make sense for my OL class to support a similar notation by overloading the shift operators:

    OL ol;
    ...  
    OL << successorNode;
    ... 
    OL >> curNode;
    
  2. (Only if the answer to 1. is "Yes") Can I go as far as to support this (i.e. the usage not supported by cout and cin for the built-in types):

    OL ol;
    ...
    successorNode >> OL;
    ...
    curNode << OL;
    
  3. (Only if the answer to 1. is "Yes") Would this usage of the shift operators make sense for standard containers:

    vector<int> v;
    v << 5; // instead of v.push_back(5)
    

EDIT: The purpose of this question is two-fold:

  • to ask whether the proposed design goes against the principle that overloaded operators should mimic the meaning of these operators for the built-in/standard types.

  • to ask why shift operators aren't used to allow less verbose usage of the standard containers.


Solution

  • The answers to your question are likely highly based on personal opinions, as there are no hard rules that allow/disallow this usage of operator overloading. So I will present arguments that should help you decide whether that is a good idea or not, instead of a hard answer.

    Regarding your first two questions:

    Think about it from the point of view of the principle of least surprise. If someone sees your code, what would he expect? Would it be immediately clear what is meant, or, as the opposite extreme, would (s)he expect something completely different? Is the overloading worth the suprise, if applicable? For example, does it make the code more clear after one has learned what the operators do? If the pros outweigh the cons, go for it! Otherwise, don't.

    As a side node to that point, I have even come across the argument that the iostream operators are a bad example for operator overloading, since they don't shift integers. However, I tend to disagree, and see this as a matter of personal opinion.

    Applied to your current situation: Might the user expect other results from calling the operator? E.g. might he expect another result from the queue? If so, don't overload. Or is the user expected to be familiar with the pseudo-code notation, and see the similarity? If so, do overload!

    Regarding the third question:

    Some people agree, some disagree. For example, the Qt framework's containers support that usage:

    QList<int> list;
    list<<5;
    

    Summary:

    The answer depends on whether it makes your code more readable (and, of course, personal opinion).

    Note: All this applies only if there is no style guide or so that prohibits this use of operator overloading!