EECS 311: DATA STRUCTURES

C++ Tips

This is a collection of miscellaneous C++ programming items relevant to the programming assignments for EECS 311. It complements but does not replace the EECS 311 Programming Standards.

IOStream Tips

Overload operator<<() and operator>>() for user-defined data classes.

If you define a class primarily to hold data, and you're printing instances of those classes or loading instances from files, then you should define operator<<() to handle output and operator>>() to handle input. That way you can change your class internals without changing code that reads and prints data. This will also let you use STL algorithms like copy() and the input and output stream iterators to read and print files of data easily.

Forward declare operator<<() and operator>>() in a class header file.

If you do the above tip, you should define the overloaded versions of operator<<() and operator>>() in a .cpp, as with all code. But you will need to tell the compiler that these definitions exist by forward declaring them in the header file, like this:

class Class {
 ...
};

std::ostream & operator<<( std::ostream &out, const Class & x);
std::istream & operator>>( std::istream &in, Class & x);

How to read to the end of a file

Do not use a loop like this to test for end of file:

while (!in.eof()) {
  in >> ...
}

This may seem like the obvious thing to do, but it will fail to do the correct thing if the file ends with spaces or empty lines, or if there's bad data in the file.

Instead, use this loop pattern:

while (in >> ...) {
  ...
}

This will run the loop as long as the input operations are successful. As soon as something "bad" happens, whether it be end of file or whatever, the above test will become false.

Handy functions and manipulators for input

Plain old operator>>() will take care of many input operations, including skipping whitespace before reading data. But for those other special situations, here are some handy things to know. In all the e:

Template Tips

Put all templated code in header files

In order for the compiler to compile code that uses templates, it has to see all of the templated code at compile time. So:

How to fix code when the compiler doesn't recognize a nested type in a templated class.

When using nested classes and typedef's, e.g., a Node class nested inside a LinkedList class, you may get a compiler error when using the nested type to declare a variable, function parameter, or return type. For example, the following toy code will not compile:

template<typename T>
class A {
  class B {
    public:
      typedef int Bint;
  };
  B::Bint b;  // will get compile error
};

The fix is to use the typename keyword to tell the compiler that something really is a type. The above can be fixed thusly:

template<typename T>
class A {
  class B {
    public:
      typedef int Bint;
  };
  typename B::Bint b;  // will compile correctly
};

Details on this problem are in the C++ FAQ..

How to fix "there are no arguments to ... that depend on a template parameter"

You'll get this kind of message when you call an inherited member function of a templated class, but the call doesn't use any templated type. The compiler looks for a regular function, outside the templated class. For example, the following toy code won't compile:

template<typename T>
class A {
  class B {
    public:
      int f() { return 1; }
  };
  
  class C: public B {
    public:
      int g() { return f(); } // f() looks like regular function
  };
};

To tell the compiler to look for the function in the templated class, you can either write this->f() or Class<T>::f(), where Class is the templated class that defines f(). The above can be fixed thusly:

template<typename T>
class A {
  class B {
    public:
      int f() { return 1; }
  };
  
  class C: public B {
    public:
      int g() { return this->f(); } // or B::f()
  };
};

Details on this problem are in the C++ FAQ..


Valid HTML 4.01 Strict