Microsoft KB Archive/182046

= How to work around bugs in template libraries by using Visual C++ =

Article ID: 182046

Article Last Modified on 12/31/2005

-

APPLIES TO


 * Microsoft Visual C++ 5.0 Enterprise Edition
 * Microsoft Visual C++ 6.0 Enterprise Edition
 * Microsoft Visual C++ 5.0 Professional Edition
 * Microsoft Visual C++ 6.0 Professional Edition
 * Microsoft Visual C++ 6.0 Standard Edition
 * Microsoft Visual C++ 2005 Express Edition
 * Microsoft Visual C++ .NET 2003 Standard Edition
 * Microsoft Visual C++ .NET 2002 Standard Edition

-



This article was previously published under Q182046



Note Microsoft Visual C++ .NET 2002 and Microsoft Visual C++ .NET 2003 support both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code. Microsoft Visual C++ 2005 supports both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model.



SUMMARY
Occasionally, bugs are found in a template library. Because all the source code for the library is available, it is tempting to go into the source code and modify the library. This is not advisable because there may be unintended side effects from the modifications to the library. In addition, technical support staff from the library vendor may decline to support a modified library.

This article describes the following methods to work around bugs in template libraries without modifying the library, by using features of the C++ language:
 * Specialize the template function that has the bug.
 * Specialize the template class member that has the bug.
 * Specialize the template class that has the bug.
 * Derive from the template class to extend its functionality.
 * Use a #define/#undef pair around a #include to change a symbol name in a template header that may be causing a conflict.



MORE INFORMATION
Below are several descriptions of how to work around bugs in a template library. One or more of these workarounds may be applicable in any given case.

The first three methods discuss specializing a template. To discover all of the specializations required, compile without optimizations (to prevent inlining any of these functions). Then either use DUMPBIN /SYMBOLS or use the /MAP linker option to generate a map file. In either case, you can find all of the specializations of the template class, function, or member used in the application. You need to provide a separate template specialization for each of these.

Method 1. Specialize the template function that has the bug.
To work around a bug in the template function CopyElements in AfxTempl.h that causes a series of elements to be incorrectly copied, you can specialize CopyElements for each type used in your program. The template declaration in AfxTempl.h is: template inline void AFXAPI CopyElements(TYPE* pDest, const TYPE* pSrc, int nCount) {  ...   } Supply a specialization for each object type that is used in CopyElements. For example, suppose you use CopyElements for an array of class MyType. Then your specialization would look similar to the following: template<> inline void AFXAPI CopyElements(MyType* pDest, const MyType* pSrc, int nCount) {  // You supply the code to copy the elements. }

Method 2. Specialize the template class member that has the bug.
To work around a bug in the template class member function deque::_Buyback, you can specialize this member function for each type of deque in your program. For instance, if you used a deque in your program, you can specialize _Buyback as follows: template<> void std::deque::_Buyback {  // You supply the code. }

Method 3. Specialize the template class that has the bug.
It is usually simpler to specialize class members that contain bugs. However, there are some circumstances when the whole class must be specialized. For instance, Visual C++ 5.0 doesn't support partial template specialization. This means that class iterator_traits does not exist, which means you can't use iterator_traits with a pointer type. In this case, you can specialize iterator_traits for each of the pointer types in your program: namespace std {

template<> struct iterator_traits { typedef ptrdiff_t difference_type; typedef MyType value_type; typedef MyType* pointer; typedef MyType& reference; typedef random_access_iterator_tag iterator_category; };

}

Method 4. Derive from the template class to extend its functionality.
Suppose that you need class CComPtr (defined in Atlbase.h) to have additional members const operator ->> const and operator const T* const. To accomplish this, create a template class and derive from it, and provide the additional member functions you need: template   class CMyComPtr : public CComPtr {  public:

operator const T* const {return (const T*)p;} const T* operator-> const {_ASSERTE(p!=NULL);return (const T*)p;}

// You supply the other required member functions. }; Your derived class should mimic the behavior of the base class as closely as possible, with the exception of the added members, to extend the functionality of the base class. The derived class does not need to supply an implementation of every member of the base class. But pay careful attention to construction and copy (assignment operators and copy constructors) so that your derived class can be used in the same ways as the base class.

Method 5. Use a #define/#undef pair around a #include to change a symbol name in a template header that may be causing a conflict.
For instance, suppose you had a source file MyProg.cpp: #include class MyTest { public: int _Ty; bool operator < (const MyTest&) const; bool operator == (const MyTest&) const; };  int main {      std::vector a;       return 1; } This results in the following error in Visual C++ 5.0:

error C2300: 'MyTest' : class does not have a destructor called '~Ty'

This is clearly a bug. The cause of the bug is that the template parameter "class _Ty" in one of the STL headers conflicts with the data member named "_Ty" in class MyTest. To work around the problem, you need to change one of the symbols--either "class _Ty" or "int _Ty". Renaming "int _Ty" in MyTest is the preferred way to work around this problem. If this is not possible, as a last resort you can change the template parameter "class _Ty" to "class _Ty0" without modifying the STL library. This can be done by surrounding the include directive for the vector header with #define/#undef directives as follows: #define _Ty _Ty0 #include #undef _Ty

Additional query words: STL ATL afxtempl.h

Keywords: kbhowto kbcpponly kbcompiler KB182046

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.