1. Not finding help here? Sign up for a free 30min tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Enum problem with the Towers of Hanoi

  1. Apr 4, 2012 #1
    A C++ computer science book gives the following program. But my compiler reports an error; "void towersOfHanoi(int): error: reference to 'left' is ambiguous".
    Code (Text):
     int lineNumber;
    enum pole { left, middle, right };
    void towersOfHanoi(int n, pole start, pole temporary, pole destination) {
      if (n > 0) {
        towersOfHanoi(n-1, start, destination, temporary);
        lineNumber++;
        cout << lineNumber << ". Move the top from the " << start
                << " pole to the " << destination << " pole.\n";
        towersOfHanoi(n-1, temporary, start, destination);
      }
     }

     void towersOfHanoi(int d)
    {
       lineNumber = 0;
       towersOfHanoi(d, left, middle, right);
    }
    ostream& operator<<(ostream& os, pole p)
    {
      switch(p) {
         case left:        os << "left";    break;
         case middle;  os << "middle";   break;
         case right:      os << "right";     break;
       }
       return os;
     }

     int main()
     {
       towersOfHanoi(3);

       return 0;
     }
    It {the book] has left me confused about enum. Can someone sort it out for me, please. Thanks in advance.
     
  2. jcsd
  3. Apr 4, 2012 #2

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    The problems have nothing to do with the enum.

    1. You aren't including <iostream>.

    2. You aren't qualifying cout or ostream as members of package std. (Alternative: You could use using namespace std; instead. Personally, I prefer seeing that std::stuff.

    3. Your switch statement has case middle; instead of case middle: .
     
  4. Apr 4, 2012 #3
    Sorry for leaving <iostream> out; I have all all of corrections included and I still get the same error and also get an ambiguous error for left, middle, and right in the overloaded operator<<(). Thanks very much.
     
  5. Apr 4, 2012 #4

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    What compiler are you using? Be specific (compiler and it's version).

    This works fine with multiple versions of g++ and clang++:

    Code (Text):
    #include <iostream>

    int lineNumber;
    enum pole { left, middle, right };

    void towersOfHanoi (int n, pole start, pole temporary, pole destination) {
       if (n > 0) {
          towersOfHanoi(n-1, start, destination, temporary);
          lineNumber++;
          std::cout << lineNumber << ". Move the top from the " << start
                       << " pole to the " << destination << " pole.\n";
          towersOfHanoi(n-1, temporary, start, destination);
       }
    }

    void towersOfHanoi (int d) {
       lineNumber = 0;
       towersOfHanoi(d, left, middle, right);
    }

    std::ostream& operator<< (std::ostream& os, pole p) {
       switch(p) {
          case left:       os << "left";      break;
          case middle:  os << "middle";  break;
          case right:     os << "right";    break;
       }  
       return os;
    }

    int main() {
       towersOfHanoi(3);

       return 0;
    }
     
  6. Apr 5, 2012 #5
    I am using g++ 4.1.2 (beta)on a RISC OS platform, but hasn't the gdb debugger ported, so it is an incomplete port as it stands; maybe that is what is wrong it is an incomplete port. I should report it as a bug to the porters to the RISC OS., I supose? Thanks again.
     
  7. Apr 5, 2012 #6

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    Here's my corrected code at codepad (http://codepad.org/rbOzNdey) and at ideone (http://ideone.com/4Az3w). This code gets your compiler error at codepad, which uses gcc 4.1.2, but not at ideone, which uses gcc 4.3.4. g++ 4.1.2 is buggy.

    The problem is that the seemingly simple #include <iostream> expands into an immense amount of code. The symbols left and right are apparently defined in the global namespace in gcc 4.1.2.

    I never define enums at global scope. There are just too many chances of a name collision. I always encapsulate enums in a class or a namespace. This code, http://codepad.org/H2UfSrgE, works just fine even in gcc 4.1.2.


    If you submit a bug report I will guarantee that they will ignore it. gcc 4.1.2 is old, old, old. So why do Linux vendors stick with it? The answer is that moving to a more modern version of gcc would make all of their code public domain. gcc 4.1.2 and gcc 4.2.1 were the last versions of gcc released under release 2 of the GNU license. Later versions of gcc use release 3. Many vendors consider that pure poison.
     
  8. Apr 5, 2012 #7
    Interesting that the overloaded << doesn't want to play as intended with the enum on those, D_H. I don't think it's recognizing a distinct type, probably because the enum is just aliases for integers.
     
  9. Apr 5, 2012 #8

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    There's no problem with the type pole, not even in the somewhat buggy g++ 4.1.2. The problem is in the enum values left and right. There is something in that big mess of code that results from #include <iostream> that pollutes the global namespace with some alternative interpretation of left and right.

    To see that this is the problem, simply rename the enum values left and right to onleft and onright. This will now work just fine in g++ 4.2.1. See http://codepad.org/k3UBIyiC for a test of this modification.
     
  10. Apr 5, 2012 #9
    I'm looking at the output, where the strings intended are not being produced.
     
  11. Apr 5, 2012 #10

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    Nice catch.

    The problem here is the compiler doesn't know about that the overloaded stream insertion operator for type pole at the time it is compiling towersOfHanoi (int, pole, pole, pole). The solution is to define or declare operator<< ( std::eek:stream&, pole) before defining towersOfHanoi (int, pole, pole, pole). This code does just that: http://codepad.org/m78tumE5.
     
  12. Apr 5, 2012 #11
    Thank you D H for the trouble you went to solve my problem and the time required by you and the information/explainations given about g++ 4.1.2. I was thinking that 4.1.2 was old alright, but I didn't think that it was buggy, because it has worked fine up to now with me. Thanks again.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook