Templating the LSDRaster object - DAV
Don’t worry, I haven’t actually changed LSDRaster in the trunk
LSDRaster uses float
s to store it’s data arrays. Floats are fine for more purposes, (they take up less memory than arrays of double
s for example, and you don’t always need the extra precision of double anyway. But I wanted an LSDRaster
object that used arrays of doubles to maintain compatibility with some other code, so I experimented with the best way of doing this.
Extra data members, overloaded functions
The easiest way is just to create a data member in the LSDRaster class that stores an array of doubles, and then write seperate functions to deal with creating this object, and manipulating it. You can overload functions if they take TNT::Array2D<float>
arguments with the corresponding <double>
typename.
Unfortunately, this leads to a lot of code duplication, and extra data members in the LSDRaster class with funny names, RasterData_dbl
, for example. It’s fine, but a bit clunky.
Templates
So I figured that it might be possible to create a templated class for LSDRaster. Templates allow a class to be spawned for different data types at run-time. The TNT::Array2D<>
class is an example of a templated class, as you specifiy the data type when you create your object, e.g TNT::Array2D< int >
, or whatever you like.
I had a shot a converting LSDRaster to a template class like so:
So, in theory, we could now create LSDRaster objects with arbitrary type for the array data (Well, not completely arbitrary - it has to be supported by TNT::Array2D.). If we wanted an array of doubles, we could do:
This is good so far, but it raises a few issues. Firstly, the declaration for an LSDRaster
object is now LSDRaster<typename>
and any instance of LSDRaster
in the code will not compile as the typename is incomplete, and your compiler will complain. Secondly, you cannot write the implementation of a template class in a separate .cpp
file, like you can with a normal class. See this SO answer for details. There are ways of getting round this, for example by including the .cpp
file in the header file, and so on.
But anyway, even if we got around the second issue above, there is still the problem that this new LSDRaster<> template has broken everyone’s code that contains any use of LSDRaster obj
. After some more reading, I though it might be possible to use a typedef
to subvert this, and stop everyone’s code from breaking.
typedef
just says that we want to use a synonym LSDRaster
to mean LSDRaster<>
(Incidentally, LSDRaster<>
without any type given inside the angle brackets, will default to float, as it was specified in the template definition as: template<typename T = float>
)
Unfortunately, you can’t do this within a class - a typedef
can’t have the same name as it’s enclosing class, and we need this inside the class because some of our functions take LSDRaster
objects (or references) as arguments. You also have to put the typedef
in all the other classes that use LSDRaster
objects.
The only way of getting around this would be to give the LSDRaster class a different name, something like:
And this would be ok, but you’d still have to change a lot of people’s code…
(TBC…)