Design question about using templates

A

Anja

Hi everyone,

I am using a third party library that uses templates quite heavily for
generalization. It is an image processing library and for example a
typical "Image" class has the following definition:

Image<PixelType, Dimensions>

The PixelType here represents the data type of the underlying
data...could be anything from chars to complex numbers and the
Dimensions are the dimensions of the image...which could be 2D to 4D
(3D and time).

Now, my problem is that I need to instantiate and store these
objects in my class. With non-templated objects it is trivial as
everything is known at compile time.

However, with this object, I do not know the PixelType and Dimensions
till run-time! So, I cannot, for example, have a member variable in a
class of the Image type. However, that is exactly what I need to do. I
need to create the image object and then later access this image
object and use its functions.

What design options do I have? I am pretty sure people have had this
problem before. What solutions can I choose from? I have banged my
head against this for the last two days but have failed to come up
with a good solution.

Typically, how the object is going to be created is that the user will
input a file at run-time and based on the file header, the Image
object of the appropriate type (defined by PixelType and Dimensions)
would be created. However, how do I store that pointer or object and
when I want to access it later, how do I ensure that the pointer is
referred to with the correct type...??

Write now I do the following to construct the object:

void ConstructReader(const char * fileName)
{
ReadHeader(fileName, int pixelType, int dimensions);
typedef Image<pixelType, dimensions> MyImage;
MyImage * image = new MyImage;
}

Someone had suggested that I have a template class for each possible
combination. However, I have about 12 pixel types and 3 dimensions to
support, which already makes a 36 possible combinations for just one
file format. I have about 10 to support!

Can someone suggest what I can do here so as not to have some class
explosion...

Hope someone can provide some suggestions.

Cheers,
Anja
 
K

kwikius

Hi everyone,

I am using a third party library that uses templates quite heavily for
generalization. It is an image processing library and for example a
typical "Image" class has the following definition:

Image<PixelType, Dimensions>

The PixelType here represents the data type of the underlying
data...could be anything from chars to complex numbers and the
Dimensions are the dimensions of the image...which could be 2D to 4D
(3D and time).

Now, my problem is that I need to instantiate and store these
objects in my class. With non-templated objects it is trivial as
everything is known at compile time.

However, with this object, I do not know the PixelType and Dimensions
till run-time! So, I cannot, for example, have a member variable in a
class of the Image type. However, that is exactly what I need to do. I
need to create the image object and then later access this image
object and use its functions.

What design options do I have? I am pretty sure people have had this
problem before. What solutions can I choose from?

<...>

It depends on the Docs for your image type.
My guess is that you are meant to supply your own types, but they will
need to conform to some set of rules e.g interface or concept.

Anyway wrapping different entities into one
can be achieved by creating a wrapper, e.g lets call it pixel . pixel
contains a pointer to an abstract base class, from where you can
derive your actual own pixel types.

IOW something like:

template <
typename PixelType,
typename Dimensionsstruct Image
{
Image( Dimensions const & d)
{
}

};

// base class for real pixel types
struct abc_pixel_type{
virtual ~abc_pixel_type(){}

};

// various real pixel types
struct col_pixel : abc_pixel_type{
/****/
};

struct gray_pixel : abc_pixel_type{
/****/
};

struct png_pixel : abc_pixel_type{
/****/
};

// common wrapper for various pixels
struct pixel{

// somehow construct form real pixels...
pixel(gray_pixel const & in)
: m_pixel(new gray_pixel(in)){}
pixel(png_pixel const & in)
: m_pixel(new png_pixel(in)){}
pixel(col_pixel const & in)
: m_pixel(new col_pixel(in)){}
~pixel(){ delete m_pixel;}
private:
abc_pixel_type * m_pixel;
};

// wrap dimensions
struct dimension{
dimension(int x, int y): m_xvalue(x),m_yvalue(y){}
private:
int m_xvalue;
int m_yvalue;
};

int main()
{
Image<pixel,dimension> my_image(dimension(1024,768));

}

However this will only be useful if you make sure you conform to the
requirements of the image type of course ....

regrads
Andy Little
 
A

Anja

Hi everyone,
I am using a third party library that uses templates quite heavily for
generalization. It is an image processing library and for example a
typical "Image" class has the following definition:
Image<PixelType, Dimensions>
The PixelType here represents the data type of the underlying
data...could be anything from chars to complex numbers and the
Dimensions are the dimensions of the image...which could be 2D to 4D
(3D and time).
Now, my problem is that I need to instantiate and store these
objects in my class. With non-templated objects it is trivial as
everything is known at compile time.
However, with this object, I do not know the PixelType and Dimensions
till run-time! So, I cannot, for example, have a member variable in a
class of the Image type. However, that is exactly what I need to do. I
need to create the image object and then later access this image
object and use its functions.
What design options do I have? I am pretty sure people have had this
problem before. What solutions can I choose from?

<...>

It depends on the Docs for your image type.
My guess is that you are meant to supply your own types, but they will
need to conform to some set of rules e.g interface or concept.

Anyway wrapping different entities into one
can be achieved by creating a wrapper, e.g lets call it pixel . pixel
contains a pointer to an abstract base class, from where you can
derive your actual own pixel types.

IOW something like:

template <
typename PixelType,
typename Dimensions

struct Image
{
Image( Dimensions const & d)
{
}

};

// base class for real pixel types
struct abc_pixel_type{
virtual ~abc_pixel_type(){}

};

// various real pixel types
struct col_pixel : abc_pixel_type{
/****/

};

struct gray_pixel : abc_pixel_type{
/****/

};

struct png_pixel : abc_pixel_type{
/****/

};

// common wrapper for various pixels
struct pixel{

// somehow construct form real pixels...
pixel(gray_pixel const & in)
: m_pixel(new gray_pixel(in)){}
pixel(png_pixel const & in)
: m_pixel(new png_pixel(in)){}
pixel(col_pixel const & in)
: m_pixel(new col_pixel(in)){}
~pixel(){ delete m_pixel;}
private:
abc_pixel_type * m_pixel;

};

// wrap dimensions
struct dimension{
dimension(int x, int y): m_xvalue(x),m_yvalue(y){}
private:
int m_xvalue;
int m_yvalue;

};

int main()
{
Image<pixel,dimension> my_image(dimension(1024,768));

}

However this will only be useful if you make sure you conform to the
requirements of the image type of course ....

regrads
Andy Little

Hi,

Thanks for your reply. This is exactly my problem! In your example,
this statement:
int main()
{
Image<pixel,dimension> my_image(dimension(1024,768));

}

Say I needed to do this in a class function and created the object on
the heap and needed to store the pointer in a class variable. I am
stuck then!

Anja
 
A

Alf P. Steinbach

* Anja:
Hi everyone,

I am using a third party library that uses templates quite heavily for
generalization. It is an image processing library and for example a
typical "Image" class has the following definition:

Image<PixelType, Dimensions>

The PixelType here represents the data type of the underlying
data...could be anything from chars to complex numbers and the
Dimensions are the dimensions of the image...which could be 2D to 4D
(3D and time).

Now, my problem is that I need to instantiate and store these
objects in my class. With non-templated objects it is trivial as
everything is known at compile time.

However, with this object, I do not know the PixelType and Dimensions
till run-time! So, I cannot, for example, have a member variable in a
class of the Image type. However, that is exactly what I need to do. I
need to create the image object and then later access this image
object and use its functions.

What design options do I have? I am pretty sure people have had this
problem before. What solutions can I choose from? I have banged my
head against this for the last two days but have failed to come up
with a good solution.

Typically, how the object is going to be created is that the user will
input a file at run-time and based on the file header, the Image
object of the appropriate type (defined by PixelType and Dimensions)
would be created. However, how do I store that pointer or object and
when I want to access it later, how do I ensure that the pointer is
referred to with the correct type...??

Write now I do the following to construct the object:

void ConstructReader(const char * fileName)
{
ReadHeader(fileName, int pixelType, int dimensions);
typedef Image<pixelType, dimensions> MyImage;
MyImage * image = new MyImage;
}

This is not valid code.

Someone had suggested that I have a template class for each possible
combination. However, I have about 12 pixel types and 3 dimensions to
support, which already makes a 36 possible combinations for just one
file format. I have about 10 to support!

Can someone suggest what I can do here so as not to have some class
explosion...

It seems that the point of the templatization is to yield efficient
operations, and that that's likely part of the reason you're using this
library in the first place.

Therefore, simply abstracting directly up to run-time typing would lose
a main advantage of the library.

Therefore, it seems you need two layers:

* A templated layer that implements the higher level image operations
you need in terms of the efficient library operations. For example,
a clear() function implemented in terms of library's setPixel().

* A dynamically typed layer that serves as glue between the rest of
the program and the library. For example, a virtual clear()
function delegating to the relevant image-type-specific clear().

For the glue layer you will by necessity only have available the pixel
types and dimensions you have chosen at compile time. So choose all
that can conceivably be useful. Don't fret about number of
combinations: just install them in an object factory repository.

Then, when you need an image of run-time pixel type and dimensions, ask
the factory repository for a factory object, then ask that factory
object for an image object.

Cheers, & hth.,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top