|
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
[.)
|