Microsoft Visual C++ 4.2 and the Standard C++ Library: Frequently Asked Questions

Microsoft Corporation

October 1996

What does the Standard C++ Library contain?

The facilities provided by the Standard C++ Library from Plum Hall are as follows:

The Standard C++ Library also incorporates the Standard C Library.

How do I use the Standard C++ Library in Visual C++ version 4.2? How does the C runtime library relate to the Standard C++ Library in Visual C++ 4.2?

Microsoft Visual C++® version 4.2 provides the Standard C++ Library facilities through included files and associated static and dynamic libraries.

A C++ program can use the different components of the Standard C++ Library by including the required header and linking with the appropriate static or dynamic library.

Tables 1 and 2 list all the Standard C++ Library headers and associated static and dynamic libraries provided by Visual C++ 4.2.

Table 1. The Standard C++ Library Headers

ALGORITHM BITSET CASSERT CCTYPE
CERRNO CFLOAT CISO646 CLIMITS
CLOCALE CMATH COMPLEX CSETJMP
CSIGNAL CSTDARG CSTDDEF CSTDIO
CSTDLIB CSTRING CTIME CWCHAR
CWCTYPE DEQUE EXCEPTION FSTREAM
FUNCTIONAL IOMANIP IOS IOSFWD
IOSTREAM ISTREAM ITERATOR LIMITS
LIST LOCALE MAP MEMORY
NEW NUMERIC OSTREAM QUEUE
SET SSTREAM STACK STDEXCEPT
STREAMBUF STRING STRSTREAM TYPEINFO
UTILITY VALARRAY VECTOR XIOSBASE
XLOCALE XLOCINFO XLOCMON XLOCNUM
XLOCTIME XMEMORY XSTDDEF XSTRING
XTREE XUTILITY

Visual C++ 4.2 includes the following static and dynamic libraries (in addition to the Microsoft Class Library [MFC]):

Note   With Visual C++ 4.2, the iostream support has been pulled out of the C runtime library and exists as an independent entity. Now Visual C++ has the following libraries:

Table 2. Static and Dynamic Libraries Included with Microsoft Visual C++ 4.2

Library types and related compiler switches Basic C runtime library Standard C++ Library Old iostream library
Single Threaded (ML) LIBC.LIB LIBCP.LIB LIBCI.LIB
Multithreaded (MT) LIBCMT.LIB LIBCPMT.LIB LIBCIMT.LIB
Multithreaded DLL version (MD) MSVCRT.LIB (import library for MSVCRT.DLL) MSVCPRT.LIB* (also uses MSVCRT.DLL) MSVCIRT.LIB (import library for MSVCIRT.DLL)
Debug Single Threaded (MLd) LIBCD.LIB LIBCPD.LIB LIBCID.LIB
Debug Multithreaded (MTd) LIBCMTD.LIB LIBCPMTD.LIB LIBCIMTD.LIB
Debug Multithreaded DLL (MDd) MSVCRTD.LIB (import library for MSVCRTD.DLL) MSVCPRTD.LIB * (also uses MSVCRTD.DLL) MSVCIRTD.LIB (import library for MSVCIRTD.DLL)

* MSVCPRT.LIB and MSVCPRTD.LIB are static libraries and do not have any DLLs related with them directly. These libraries are also dependent on MSVCRT.DLL and MSVCRTD.DLL, respectively. Any applications that use MSVCPRT.LIB or MSVCPRTD.LIB and use the "Ignore Default Library" (/NOD or NODEFAULTLIB) option, must link MSVCPRT.LIB(or MSVCPRTD.LIB) and MSVCRT.LIB (or MSVCRTD.LIB ), otherwise linker errors (such as LNK2001: unresolved externals in MSVCPRT.LIB or MSVCPRTD.LIB) will be produced.

Case 1. Consider the following sample C++ program where test.cpp uses the Standard C++ Library iostream to print "Hello World".

// test.cpp
#include <iostream>
void main()
{
    cout << "Hello World" << endl ;
}
Building test.cpp using Will cause test.cpp to link with
cl /ML /GX test.cpp LIBC.LIB, LIBCP.LIB
cl /MLd /GX test.cpp LIBCD.LIB, LIBCPD.LIB
cl /MT /GX test.cpp LIBCMT.LIB, LIBCPMT.LIB
cl /MTd /GX test.cpp LIBCMTD.LIB, LIBCPMTD.LIB
cl /MD /GX test.cpp MSVCRT.LIB, MSVCPRT.LIB
cl /MDd /GX test.cpp MSVCRTD.LIB, MSVCPRTD.LIB

In Case 1, test.cpp used the Standard C++ Library input/output component to print "Hello World". The program just includes the Standard C++ Library header <iostream>. When compiling the program, specify a runtime library option: /ML[d],/MT[d], or /MD[d]. The program will then link with a basic runtime library (for example, LIBC.LIB with the /ML option) and a Standard C++ Library (for example, LIBCP.LIB with the /ML option). The /GX option enables exception handling. Exception handling must be enabled for any programs that use the Standard C++ Library.

It is important to remember that starting with Visual C++ 4.2, a C++ program, depending on the runtime library compiler option specified (/ML[d],/MT[d], or /MD[d]), will always link with one Basic C runtime library and, depending on headers included, link with either a Standard C++ Library (as in the case 1), an old iostream library (as in Case 3), or neither (as in Case 2).

Case 2. Consider the following sample program:

// test.cpp
void main()
{
}
Building test.cpp using Will cause test.cpp to link with
cl /ML test.cpp LIBC.LIB
cl /MLd test.cpp LIBCD.LIB
cl /MT test.cpp LIBCMT.LIB
cl /MTd test.cpp LIBCMTD.LIB
cl /MD test.cpp MSVCRT.LIB
cl /MDd test.cpp MSVCRTD.LIB

Case 3. Consider the following sample program:

// test.cpp
#include <iostream.h>
void main()
{
}
Building test.cpp using Will cause test.cpp to link with
cl /ML test.cpp LIBC.LIB, LIBCI.LIB
cl /MLd test.cpp LIBCD.LIB, LIBCID.LIB
cl /MT test.cpp LIBCMT.LIB, LIBCIMT.LIB
cl /MTd test.cpp LIBCMTD.LIB, LIBCIMTD.LIB
cl /MD test.cpp MSVCRT.LIB, MSVCIRT.LIB
cl /MDd test.cpp MSVCRTD.LIB, MSVCIRTD.LIB

I am receiving the following compiler error: "C2373: '>=": redefinition ; different type modifiers;" when my application includes the header <iostream> and the MFC header <afxwin.h> The following piece of code demonstrates the error. What is wrong with the code?

#include <afxwin.h>
#include <iostream>

void main()
{
    CString cstr1("Hello"), cstr2("World") ;
   
    // following line causes a C2373
    if ( cstr1 >= cstr2 )
        cout << "ctsr1 >= ctsr2" ;
    
}

The problem is caused by an ambiguity during function-overload resolution for the operator>=() function. This is an inadvertent conflict between the MFC global definition of operator>= and the Standard C++ Library global function template operator>=().

Here is the MFC global definition of the operator>=() function. It is used to compare CString objects.

BOOL operator >=( const CString& s1, const CString& s2 );

Here is the Standard C++ Library global function template operator>=(). This function is defined in the header <utility>. Including the header <iostream> causes the header <utility> to be included in the source file.

template<class _TYPE> Inline
bool operator>=(const _TYPE& _X, const _TYPE& _Y) ;

The problem occurs in the case of CString during function-overload resolution for the line

    if ( cstr1 >= cstr2 )

which is the same as calling operator>=(cstr1, ctsr2). CString defines the operator>=() function as a friend function. When the compiler looks for the appropriate function to call, it first looks for an exact match for the arguments. First, it finds operator>=(const CString, const CString) defined; but this is not an exact match, as cstr1 and cstr2 are CStrings, not const CStrings. Next, it instantiates the template class described above and generates another version of operator>=(const CString, const CString), which is still not an exact match. Finally, it attempts the least-intrusive conversion, which is from CString to const CString. When this is done, it finds there are two definitions for operator>=(const CString, const CString), hence the ambiguity and the error.

There are two workarounds to resolve this problem:

  1. Use the operator<() function and operator==() function for comparison. For example, in the above code change
    if(cstr1 >= cstr2)
    

    to:

    if(!(cstr1 < cstr2))
    
  2. Use the old iostream library by including <iostream.h>. If you are using any other components of the Standard C++ Library in your program, this will not work. You cannot mix the old iostream library headers with the Standard C++ Library headers. See the discussion on the compiler error C2371.

I have an MFC program that uses the Standard C++ Library. When I run the program in the debugger, it reports memory leaks. The leaks are reported in objects that are part of the Standard C++ Libraries—not in my code.

This is a known problem in Visual C++ 4.2. Most of the leaks are constant (they do not grow in time) and small. There is no known workaround at this time. Microsoft is researching this issue, and the issue will be addressed in a future release of Visual C++.

When I try to compile a source file with "#include <stl.h>", I receive several compiler errors, which are all in the STL header files. Is there a bug in STL?

STL.H was included with Visual C++ 4.2 by mistake. It is not part of the American National Standards Institute (ANSI) standard for Standard C++ Libraries and should not be used. Instead, include the individual header files associated with the particular STL component(s) the program is using. The sample code below, for example, will compile and run correctly if "#include <stl.h>" is changed to "#include <vector>".

//workaround: change the following line to #include <vector>
#include <stl.h>

//workaround: change the "typedef" to:
//typedef vector<int, allocator<int> > INTVECT;  // See Question 7
typedef vector<int> INTVECT;

void main()
{
     INTVECT ivect;
}

I am receiving compiler error "C2976: 'istream_iterator' : too few template arguments when attempting to instantiate an istream_iterator as follows: ostream_iterator<int> MyIterator;". I also have a similar problem with istream_iterator. Most of the books on STL programming use the above syntax to instantiate a stream iterator. What are the other parameters I need to specify?

In Visual C++ 4.2, when instantiating stream iterators you need to use the following syntax:

ostream_iterator<int, char, char_traits<char> > ostrIter ;

Here are the definitions of the istream_iterator and ostream_iterator class templates in Visual C++ 4.2:

template <class T, class charT, class traits = char_traits<charT> > class istream_iterator;
template <class T, class charT, class traits = char_traits<charT> > class ostream_iterator;

You need to specify the two extra parameters char, and char_traits<char> when instantiating stream iterators. This is because Visual C++ 4.2 does not support the following syntax:

template <class T, class charT, class traits = char_traits<charT> >

What do these extra parameters mean?

For more information on traits, see the article "A New and Useful Template Technique: 'TRAITS.' " by Nathan Myers, C++ Report, June 1995.

I am receiving the compiler error "C2976: 'identifier': too few template parameters," when instantiating STL containers. Why do the STL containers of Visual C++ 4.2 require an extra parameter? What is that extra parameter?

Several STL components use default template arguments. The ANSI draft specification for the STL container classes (such as vector) specifies that the second template argument (the allocator) must have a default value of "allocator", as follows:

template<class T, class Allocator = allocator> class vector;

The predefined allocator class uses member templates. Visual C++ 4.2 does not support the use of member templates.

Because it is not possible to implement the allocator class directly, the allocator has been implemented as a template class in the current implementation of the STL. The problem lies in attempting to use the templated allocator class as a default template argument. Consider the following:

template<class T, class Allocator = allocator<T> > class vector;

Visual C++ 4.2 does not support this syntax. This makes it necessary, in the case of STL containers, to remove the default template argument for the allocator. The definition of vector now becomes:

template<class T, class Allocator> class vector;

The side effect of this is that declaring a container will now require that you explicitly specify the allocator class as a template argument. Consider the following declaration of an int vector:

vector<int> myVector; 

This will cause the following compiler error:

Compiler error C2976 : 'vector' : too few template parameters

To correct the error, the declaration must be changed to:

vector<int, allocator<int> > myVector;

IMPORTANT INFORMATION: Using a typedef

It is good programming practice to use typedef statements when instantiating template classes. Using a typedef has the following advantages:

For example, if you have a class template as follows:

template <class A, class B, class C, class D>
class Test
{
} ;

you can instantiate a template class using the above class template as follows:

Test<int, int, float, float> ifClass1 ;

For another instantiation in a different source file, you would repeat:

Test<int, int, float, float> ifClass2 ;

Now if the definition of the Test class template changes as follows

  template <class A, class B, class C, class D, class E>
class Test
{
} ;

you will have to modify every instantiation in your source code to reflect the change—not a very easy task.

Using a typedef makes life easier, because you only need to change the typedef statement. So use a typedef as follows:

  template <class A, class B, class C, class D>
class Test
{
} ;

typedef Test<int, int, float, float > MYCLASS ;

MYCLASS myObj1 ;
MYCLASS myObj2 ;

Now if the Test class template definition changes, you only need to change the typedef:

  template <class A, class B, class C, class D, class E>
class Test
{
} ;

typedef Test<int, int, float, float, char> MYCLASS ;

MYCLASS myObj1 ;
MYCLASS myObj2 ;

You can save some valuable time and reduce the frustration by using a typedef!

I am receiving compiler error "C2371: 'identifier' redefinition; different basic types". What is causing this?

Mixing Standard C++ Library headers and old iostream library headers will cause this error, even if they are included in different source files.

Table 3. Old iostream Library Headers

FSTREAM.H IOMANIP.H IOS.H
IOSTREAM.H ISTREAM.H OSTREAM.H
STDIOSTR.H STREAMB.H STRSTREA.H

Table 4. Standard C++ Library Headers

ALGORITHM BITSET COMPLEX
DEQUE FSTREAM FUNCTIONAL
IOMANIP IOS IOSFWD
IOSTREAM ISTREAM ITERATOR
LIMITS LIST LOCALE
MAP MEMORY NUMERIC
OSTREAM QUEUE SET
SSTREAM STACK STDEXCEPT
STREAMBUF STRING STRSTREAM
TYPEINFO UTILITY VALARRAY
VECTOR XIOSBASE XLOCALE
XLOCINFO XLOCMON XLOCNUM
XLOCTIME XMEMORY XSTRING
XTREE XUTILITY YMATH.H

I have a project that was built with the "Ignore Default Libraries" option (/NOD or /NODEFAULTLIB). With Visual C++ 4.2, I am receiving linker error "LNK2001: unresolved external symbol 'symbol' " on all iostream function calls. What has changed?

The iostream functions have been removed from the C runtime library.

If you are using the old iostream functions, you will need to add an additional library as follows: LIBCI.LIB with the single-threaded, or </ML>, option; LIBCMI.LIB with the multithreaded, or </MT>, option; or MSVCIRT.LIB with the multithreaded dll, or </MD>, option.

If you are using the new iostream functions included with the Standard C++ Library, you will need to add an additional library as follows: LIBCP.LIB with the single-threaded, or </ML>, option; LIBCMP.LIB with the multithreaded, or </MT>, option; or MSVCPRT.LIB with the multithreaded dll, or </MD>, option.

Do not mix different versions of the libraries. For example, if you are using the single-threaded version of the C runtime library, you must also use the single-threaded version of the iostream library or Standard C++ Library.

Note   You cannot mix calls to the old iostream library functions and the new Standard C++ Library iostream functions.

See related issues:

I am receiving compiler warnings C4786 and/or C4788. None of the symbols in my program is anywhere near 255 characters in length. What is causing this?

C4786 and C4788 are issued when a symbol's name exceeds 255 characters in length. This often happens with templates and, especially, with STL components.

Ignoring this warning is usually safe. Use a #pragma warning (disable: 4786,4788) to suppress the messages.

See "Compiler Warning (level 1) C4786" in the Visual C++ documentation in the MSDN library for further details.

I am receiving compiler warning "C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX." What does that mean?

Programs that use the Standard C++ library must be compiled with C++ exception handling enabled.

To enable C++ exception handling in Visual C++:

I am receiving compiler error C2146, followed by compiler error C2065, and finally compiler error C2143, all pointing to the same line in my source. What does this mean?

This sequence of errors can be caused by the following type of construct:

vector<int, allocator<int>> iV;

The problem is caused by the consecutive ">>" at the end of the declaration. The solution is to put a space between them, so the above becomes:

vector<int, allocator<int> > iV;

This is consistent with the proposed ANSI specification.

Can I use existing static or dynamic link libraries built with Visual C++ 4.0 or Visual C++ 4.1 with applications being developed using Visual C++ 4.2?

If your application is not going to use the Standard C++ Library, you can use the existing libraries in your application as is.

If your application is going to use the Standard C++ Library, you need to consider the following issues:

For related issues see:

I ported my application from Visual C++ 4.1 to Visual C++ 4.2. I do not want to use the Standard C++ Library. So, how do I retain the old iostream functionality?

If you want to retain the old iostream library, include one or more of the old iostream header files in your code. Do not use the new Standard C++ headers. You cannot mix calls to the old iostream and the new Standard C++ library. For further details, see "Issues Surrounding iostream, STL and the Standard C++ Library," or the response to "How do I use the Standard C++ Library in Visual C++ 4.2?".

How do I make the Standard C++ Library the default library for my application?

If you want to make the Standard C++ Libraries the default library, include one or more of the new Standard C++ headers. Remember, you cannot mix calls to the old iostream and the new Standard C++ library. Existing libraries (static or dynamic link) that use iostream functions will have to be rebuilt using Standard C++ Library iostream functions. For further details, see "Issues Surrounding iostream, STL and the Standard C++ Library," or the response to "How do I use the Standard C++ Library in Visual C++ 4.2?".