Guest Column
January 2007
Tao Ma

Production System New Release

The latest release of our ISIP Production System is finally here! This release (r02_n00) is fully compatible with the latest GNU C++ compiler, GCC4.1.1 (It has been tested with both GCC4.1.0 and GCC4.1.1.) Since version 3.4, G++ is much closer to fully conforming to the ISO/ANSI C++ standard. A lot of code which used to be accepted in previous versions will now be rejected. It has taken months for all the code re-writing and the testing. Click here to download our state-of-the-art software to speed up your speech recognition research.

Many significant changes were made in the Math and Data Structure libraries in order to make the template structures compatible with GCC 4.1.1. For example, all non-dependent names inside templates are now looked up and bound at definition time (while parsing the code), instead of later when the template is instantiated. The most common coding changes we made were:

Significant Changes

  • When allocating an array with a new expression, GCC used to allow parentheses around the type name. This is actually ill-formed and it is now rejected:
    		int* a = new (int)[10];    // error, not accepted anymore
    		int* a = new int[10];      // OK
  • In an explicit instantiation of a class template, you must use class or struct before the template-id:
    		template <int N>
    		class A {};
    	
    		template A<0>;         // error, not accepted anymore
    		template class A<0>;   // OK
  • G++ no longer accepts attributes for a declarator after the initializer associated with that declarator. For example,
    	        X x(1) __attribute__((...));
    is no longer accepted. Instead, use:
    	        X x __attribute__((...)) (1);
  • Friend declarations that refer to template specializations are rejected if the template has not already been declared. For example,
    		template <typename T>
    		class C {
    		  friend void f<> (C&);
    		};

    is rejected. You must first declare f as a template,

    		template <typename T>
    		void f(T);
  • You must use template <> to introduce template specializations, as required by the standard. For example,
    		template <typename T>
    		struct S;
    
    		struct S<int> { };

    is rejected. You must write,

    		template <> struct S<int> {};
  • Using a name introduced by a typedef in a friend declaration or in an explicit instantiation is now rejected, as specified by the ISO C++ standard.
    		class A;
    		typedef A B;
    		class C { 
    		  friend class B;      // error, no typedef name here
    		  friend B;            // error, friend always needs class/struct/enum
    		  friend class A;      // OK
    		};
    	
    		template <int> class Q {};
    		typedef Q<0> R;
    		template class R;      // error, no typedef name here
    		template class Q<0>;   // OK
  • In templates, all non-dependent names are now looked up and bound at definition time (while parsing the code), instead of later when the template is instantiated. For instance:
    		void foo(int);
    
    		template <int> struct A {
    		  static void bar(void){
    		    foo('a');
    		  }
    		};
    
    		void foo(char);
    
    		int main()
    		{
    		  A<0>::bar();    // Calls foo(int), used to call foo(char).
    		}
    		
  • In a template definition, unqualified names will no longer find members of a dependent base (as specified by [temp.dep]/3 in the C++ standard). For example,
    		template <typename T> struct B {
    		  int m;
    		  int n;
    		  int f ();
    		  int g ();
    		};
    		int n;
    		int g ();
    		template <typename T> struct C : B<T> {
    		  void h ()
    		  {
    		    m = 0; // error
    		    f ();  // error
    		    n = 0; // ::n is modified
    		    g ();  // ::g is called
    		  }
    		};

    You must make the names dependent, e.g. by prefixing them with this->. Here is the corrected definition of C<T>::h,

    		template <typename T> void C<T>::h ()
    		{
    		  this->m = 0;
    		  this->f ();
    		  this->n = 0
    		  this->g ();
    		}

    As an alternative solution, you may use using declarations instead of this->:

    		template <typename T> struct C : B<T> {
    		  using B<T>::m;
    		  using B<T>::f;
    		  using B<T>::n;
    		  using B<T>::g;
    		  void h ()
    		  {
    		    m = 0;
    		    f ();
    		    n = 0;
    		    g ();
    		  }
    		};
  • Inside the scope of a template class, the name of the class itself can be treated as either a class or a template. So GCC used to accept the class name as argument of type template, and template template parameter. However this is not C++ standard compliant. Now the name is not treated as a valid template template argument unless you qualify the name by its scope. For example, the code below no longer compiles.
    	        template <template <class> class TT> class X {};
    	        template <class T> class Y {
    	          X<Y> x; // Invalid, Y is always a type template parameter.
    	        };

    The valid code for the above example is

    	          X< ::Y> x; // Valid.

    (Notice the space between < and : to prevent GCC to interpret this as a digraph for [.)


Footer
ISIP

Home | Projects | Publications | What's New | Contact | About Us | Search | Up

Please direct questions or comments to Isip_help@ece.msstate.edu

Mississippi State University
Footer