Template GotchasYou can't separate your class definitions into source and header files like you normally wouldThe problem is that most compilers do not remember the details between different source (.cpp, .cxx etc) files. As stated above, classes and functions that you define with templates aren't really classes and functions. They are considered template patterns and these patterns are used to generate the actual classes. This causes issues with the compiler, since templates aren't really classes, and only become classes when you actually declare them. The compiler can't actually allow you to have your implementation in your source file and header (h/.hpp etc) without a bit of tinkering around. A lot of people like to put their actual implementation in the source file while keeping the class declaration in header files. This allows them to glance through the header file to see the functionality the class provides. However, this is not easy to achieve with templates. One solution is to have all your code inlined within the header file. The main disadvantage to this technique is that you loose the benefit of separating the implementation from the declaration and the ability to see the functionality of a class at a glance. What many people do is place both their implementation and declaration in the header file. They do not inline the actual implementation but rather keep it separate from the declaration. For example: template <typename T> class MyClass { private: T x; public: T GetX(); }; template <typename T> T MyClass<T>::GetX() { return x; } One common mistake many people make when separating the code from the implementation, is that they forget that every bit of code outside the class declaration has to be within its own template declaration. Another common mistake is to declare the implementation just as you would inside the class like MyClass::GetX(). This is not correct. As pointed out before, once you use templates it's no longer MyClass, it's MyClass<T>. Another approach is to separate the implementation into another file. You include this file at the bottom of the header using the #include directive. Some people keep the extension ".cpp". However this file must not be included in the compilation process and therefore a extension like ".tpl" is better. In Visual C++, for example, you have to make sure you do not include it in the project manager. Other compiler implementations make sure it's not within the makefile. Another solution is to use the 'export' keyword to achieve this functionality; however, at this time only the Comeau compiler actually supports this keyword. Although there is a lot of talk in the standards community about removing the export keyword, it will remain in the next revision of the C++ Standard because it provides at least a conceptual benefit. Templates with Smart PointersSmart pointers are objects that manage the destruction and aspects of a pointer's lifetime, and take care of a lot of the safety issues for you. Through the use of operator overloading they are designed to give you the "feel" of an ordinary pointer. One smart pointer that the C++ standard provides is std::auto_ptr. The standard auto_ptr provides a lot of great functionality, however, one of its big problems is that you can't really use it with C++ containers or anything using a template. The C++ standard has defined using auto_ptr with templates and containers as undesirable due to the ownership transfer semantics. STL Containers and smart pointers have become quite popular now-a-days. Containers like std::vector allow you the flexibility of allowing quick and easy storage for your objects and values without having to roll out your own solutions like linked lists. Smart pointers allow you to have your memory cleaned up efficiently without having to worry about the details yourself. Containers like std::vector don't provide any sort of memory cleanup. If you use a std::vector with a pointer it's your responsibility to go through and cleanup the pointers it contains. Consider using boost::shared_ptr from the boost suite of libraries. Not only will it work with templates and STL containers but it also has a lot of advanced features like reference counting etc. I have been using it myself for all my smart pointer needs. You can find information about it here: http://www.boost.org. Another popular Smart Pointer is part of the Loki library by Andrei Alexandrescu and you can find information about it here: http://sourceforge.net/projects/loki-lib/. Some people get tripped up when defining a smart pointer and container combo. For example a lot of people might initially define it as this: std::vector<boost::smart_ptr<CGameObject>> ObjectContainer; The difficulty is the >> after CGameObject. This gets interpreted as the bit shift operator. The way around this is to simply place a space between the first and second like so: std::vector<boost::smart_ptr<CGameObject> > ObjectContainer; I'm using Visual C++ 6, and I'm getting compile errors/warnings. Am I doing something wrong?Not necessarily. Visual C++ 6 was released just before the standardisation committee finished finalising the C++ standard. Therefore some of the features introduced in the standard are incomplete or incorrect. One of the areas that suffer quite a bit is templates. The implementation of STL provided by Microsoft is actually licensed from Dinkumware. Some advanced features may be missing in Visual C++ 6 like partial template specialisation. My top recommendation to remedy this problem is to upgrade to Visual C++ 7.1 (2003 edition) or above. This version of Visual C++ is over 98% standards compliant and the majority of issues in early versions have been fixed. If you are a student you can get a cheap copy of Visual Studio Academic version. It provides similar level of functionality as the Pro version of Visual Studio with a few extra student tools. It does however have licensing issues. Also the standard version of Visual C++ 7.1 is quite cheap and is enough for the hobbyist game programmer with optimisation features missing. If you end up keeping Visual C++ 6, for whatever reasons, you might want to consider the following options.
Unfortunately, some of the template problems with Visual C++ 6 are inherent to the compiler and changing the library may not help resolve all of them. Resources/Referenceshttp://msdn.microsoft.com/ - The definitive source of MSVC information. http://www.sgi.com/tech/stl/ - More details on STL than MSDN. http://www.gotw.ca/ - Herb Sutter - Guru of the Week http://www.cuj.com - C++ Users Journal Effective STL, Scott Meyers Effective C++, Scott Meyers More Effective C++, Scott Meyers |
|