next up previous
Next: Typedef Bug Up: Notes on using the Previous: Compiling

Upcasting Bug

The g++ compiler cannot do a few things the Sun native compiler can. In particular if a global function with templated arguments of some base class is called with a class derived from the base class it will not find a match. (i.e. it cannot do upcasts)

This problem is particularly endemic in the Arrays module and for these classes particular solution has been devised. The Array class (and hence derived classes) have an upcasting member function called arrayCast() (or ac() for short).

For example in the aips/Arrays/ArrayMath.h class there is a function

   T max(const Array<T> &a)
which will not compile when called with a vector as an argument. ie.
   Vector<Float> vec(4);
   cout << max(vec) << endl; // error flagged on this line!
but will compile if rewritten as
   cout << max(vec.arrayCast()) << endl;

This solution gets particularly useful when doing arithmetic on Vectors because g++ will complain about:

   Vector<Float> v1(4), v2(4);
   v1 += v2;
And this should be changed to
   v1.arrayCast() += v2.arrayCast(); // make the cast explicit
   or 
   v1.ac() += v2.ac(); // emphasize the arithmetic not the cast

This problem has also been recently seen in the Lattice classes and a corresponding set of member functions called latticeCast() (or lc() for short), have been written.

On rare occasions you may need to selectively do an upcast when a templated argument can be either a builtin data type (Int/Float etc.) or an Array (Vector/Matrix etc.). For these occasions the functions at_c() & at_cc() exist. These global functions only upcast Arrays and leave the builtin data types alone. They are defined in the Array, Vector, Matrix & Cube classesgif, and in aips.h for the builtin data types (and in String.h also).

The difference between the two functions is that at_c() is takes a non-constant input arguement while at_cc() takes a constant input arguement. Two function names are used rather than overloading just one because of what we think is a bug in the g++ compiler.

An example of this function in use in is the Measures module where a Quantum has standard templates of Double and Vector<Double>. Then the floor function is defined in QMath.cc as:

template <class Qtype>
Quantum<Qtype> floor(const Quantum<Qtype> &left) {
    Qtype tmp = left.getValue(); 
    Qtype ret;
    at_c(ret) = floor(at_c(tmp));
    return (Quantum<Qtype>(ret,left));
}

If you see this problem in other class hierarchies, you can do an explicit type cast but are instead urged to create an upcasting member function in the base class. The advantage of using member functions, rather than explicit casts, is that if g++ is ever able to do upcasts in the future it will then be easier to search for the upcasting functions and remove them. Please tell me if you do this, so I can add it to the documentation.

It is expected that this bug will disappear in g++ version 2.8.0 (private communication between Brian and one of the g++ developers).


next up previous
Next: Typedef Bug Up: Notes on using the Previous: Compiling

Ralph Marson
Wed Aug 28 17:15:27 MDT 1996