1 Migration Guide: from gcc 2.95 to gcc 3.2 ( prestandard C++ code -> standard C++ code)

Here is a quick rundown of some of the most basic changes that the migration to gcc 3.2 will require. There are other changes, but most users probably won't need to worry about them. Most of the changes which came with gcc 3.2 are related to C++ ABI (application binary interface).

include standard headers without .h

For all of 32 official include files, listed in the C++ standard in section 17.4.1.2

For an example: Use
#include <math>
#include <stdio>
#include <iostream> 
#include <iomanip> 
#include <fstream> 

Instead of
#include <math.h>
#include <stdio.h>
#include <iostream.h> 
#include <iomanip.h> 
#include <fstream.h>

C headers and C++ headers

C++ provides the standard C89 library as part of its library.

C99 adds a few header files that are not included as part of the standard C++ library, though:
<complex.h>   
<fenv.h>   
<inttypes.h>   
<stdbool.h>   
<stdint.h>   
<tgmath.h>   

Even though C++ provides the C89 standard C library headers as part of its library, it deems their use as deprecated. Instead, it encourages programmers to prefer the equivalent set of C++ header files which provide the same functionality as the C header files:

<math.h> replaced by <cmath> <stddef.h> replaced by <cstddef> <stdio.h> replaced by <cstdio> <stdlib.h> replaced by <cstdlib> etc. etc.

Deprecating the use of the C header files thus makes the following valid C++98 program possibly invalid under a future revision of standard C++:
#include <stdio.h>     // Deprecated in C++

int main(void)
{
        printf("Hello, world\n");
        return 0;
} 

The program can be modified by removing the use of deprecated features in order to make it portable to future implementations of standard C++:
#ifdef __cplusplus
#include <cstdio>     // C++ only
using std::printf;
#else
#include <stdio.h>    // C only
#endif

int main(void)
{
        printf("Hello, world\n");
        return 0;
} 

clog identifier

C99 declares clog() in <math.h> as the complex natural logarithm function.

C++ declares std::clog in <iostream> as the name of the standard error logging output stream (analogous to the stderr stream). This name is placed into the global namespace if the <math.h> header is included, and refers to the logarithm function. If <math.h> defines clog as a preprocessor macro name, it can cause problems with other C++ code.
// C++ code

#include <iostream>
using std::clog;

#include <math.h>               // Possible conflict

void foo(void)
{
        clog << clog(2.718281828) << endl;
        // Possible conflict
} 

Including both the and the <cmath> headers in C++ code places both clog names into the std:: namespace, one being a variable and the other being a function, which should not cause any conflicts.
// C++ code

#include <iostream>
#include <cmath>

void foo(void)
{
        std::clog << std::clog(2.718281828) << endl;
        // No conflict; different types
}

void bar(void)
{
        complex double  (* fp)(complex double);
        
        fp = &std::clog;            // Unambiguous
} 

It would appear that the safest approach to this potential conflict would be to avoid using both forms of clog within the same source file.

std namespace is now required for many objects:

Usage of Namespace “std::” is mandatory for objects of the standard library!

  • all STL containers: eg string, vector, list, etc
  • i/o objects, eg cout, cerr, endl. Don't forget to #include  <iostream>
  • i/o formatting flags, e.g. hex, dec.

ALERT! Remember that while it's fine to do a use namespace std in your .cxx files, this should NEVER be done in a header (or .icc).

cerr and cout are defined in <iostream>

You must include this file in order to use them.

for ostream formatting, use the std::ios::fmtflags

forward_iterator is now just an iterator.

You can use the macro HAVE_ITERATOR to test for its presence:
#ifdef HAVE_ITERATOR
// std c++ (gcc 3.2)
#else 
// old stl iterator
#endif

ios::open_mode has become ios::openmode

strstream has changed name to become stringstream.

and the include file name has also changed: #include <strstream> --> #include <sstream> std::strstream --> std::stringstream similarly for ostrstream, istrstream

ALERT! Remember not to delete the buffer after use, as the stringstream.str() builds a string, not a char[] as was the case with strstream.str(). With gcc 3.2, you no longer need to "freeze" the stream to prevent a memory leak.

Usage:
  • change include <strstream> into include <sstream>
  • change (o/i)strstream into (o/i)stringstream
  • remove freeze() calls

Your code needs to be able to handle both gcc 2.95 and gcc 3.2 if it's to compile on all platforms. You can do this with by using the macro definition HAVE_NEW_IOSTREAMS, which is defined for gcc 3.2 in AtlasPolicy:
#ifdef HAVE_NEW_IOSTREAMS
#include <sstream>
typedef std::stringstream my_sstream;
#else
#include <strstream>
typedef strstream my_sstream;
#endif

Then use the typedef my_sstream in your code in place of the strstream or stringstream.

Method streambuf::stossc replaced

Calls to the method streambuf::stossc() should be replaced by calls streambuf::sbumpc(), with the result cast to void. For instance, change rdbuf->stossc to (void)rdbuf->sbumpc().

inline declarations must be in the header file, and not in the source, or runtime errors may occur.

throw statements

If a class B inherits A and a virtual method A is redefined in B, the eventual throw specification in A must be there in B too.
(compatible with gcc 2.95 No #ifdef)
gcc 2.95:
class A {
        virtual void foo (int a) throws MyException;
}
class B {
        virtual void foo (int a);
}

gcc 3.2:
class A {
        virtual void foo (int a) throws MyException;
}
class B {
        virtual void foo (int a) throws;
}

enum types

Enum and int types are no more related. Thus you can no more use an int to initiate an object of type enum
gcc 2.95:
enum smallInt { ZERO, ONE, TWO, THREE, FOUR };
smallInt a = 0;

gcc 3.2:
enum smallInt { ZERO, ONE, TWO, THREE, FOUR };
smallInt a = ZERO;

stronger type checking

Enumerations and long or integers can no longer be mixed. This applies notably to the std::_Ios_Iostate and std::_Ios_Fmtflags type which were up to now replaced by longs.

std::smanip is no more known to the compiler.

It was replaced by a whole set of new types, namely _Setfill<_CharT>, _Setiosflags, _Resetiosflags, _Setbase, _Setprecision and _Setw.

Ambiguous templates ("warning: implicit typename is deprecated")

In some cases template declarations can be ambiguous.
gcc 3.2:
int y;
template <class T> void g(T& v) {
        T::x(y);
        T::z * y;
}

  • T::x could be a function call (function x declared in class T) or a variable declaration (variable y of type T::x with perverse parenthesis).
  • T::z * could be a type or y could be multiplied by the constant T::z

Typeparams

In order to resolve the ambiguity, one has to tell the compiler whether T::x is a type
gcc 3.2:
template <class T> void g(T& v) {
        typename T::x(y);
}

This is typically the case with containers
gcc 2.95:
typedef std::vector<TYPE*> Data;
typedef Data::iterator (myIterator);

gcc 3.2:
typedef std::vector<TYPE*> Data;
typedef typename Data::iterator (myIterator);

the C++ specification says
“The typename keyword is needed whenever a type name depends on a template parameter”

string::compare

The syntax is a little different now.
2.95:
string::compare(string,start,end);

3.2:
string::compare(start,end,string);

iostream::form

Get rid of this method by using stream operator << instead.

macro with parameters and ##

When defining a macro with parameters, the use of ## is more strict:
you can NO more put it when not necessary. As an example:
#define IMPLEMENT_SOLID(x) \
static const SolidFactory<##x##> s_##x##Factory ; \
const ISolidFactory&##x##Factory = s_##x##Factory ;

has to be :
#define IMPLEMENT_SOLID(x) \
static const SolidFactory<x> s_##x##Factory ; \
const ISolidFactory& x##Factory = s_##x##Factory ;

hash_map

The include file hash_map of gcc 2.95.2 has become ext/hashmap. On top of that, the type is no more std::hash_map but __gcc_cxx::hash_map. One way of dealing with that is to use hash_map (without a namespace) and do this for inclusion:
#ifdef _WIN32
#include "stl_hash.h"
using std::hash_map;
#else
#if defined (__GNUC__) && ( __GNUC__ <= 2 )
#include <hash_map>
using std::hash_map;
#else
#include <ext/hash_map>
using __gnu_cxx::hash_map;
#endif
#endif

If you need code to behave differently for gcc 3.2 and gcc 2.95

make use of the macro definition __GNUC__, which is equivalent to the major version of gcc, ie "2" for 2.95, and "3" for 3.2:
#if (__GNUC__) && (__GNUC__ > 2) 
// put your gcc 3.2 specific code here
#else
// put your gcc 2.95 specific code here
#endif

-- AnarManafov - 24 Mar 2005
Topic revision: r10 - 2005-04-30, AnarManafov
 
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding GSI Wiki? Send feedback
Imprint (in German)
Privacy Policy (in German)