Design question about using templates

Discussion in 'C++' started by Anja, Feb 22, 2008.

  1. Anja

    Anja Guest

    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
     
    Anja, Feb 22, 2008
    #1
    1. Advertising

  2. Anja

    kwikius Guest

    On Feb 22, 1:27 am, Anja <> wrote:
    > 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
     
    kwikius, Feb 22, 2008
    #2
    1. Advertising

  3. Anja

    Anja Guest

    On Feb 22, 2:45 am, kwikius <> wrote:
    > On Feb 22, 1:27 am, Anja <> wrote:
    >
    >
    >
    > > 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
     
    Anja, Feb 22, 2008
    #3
  4. * 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

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Feb 22, 2008
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Fred
    Replies:
    1
    Views:
    635
    Neredbojias
    Sep 26, 2005
  2. John Harrison

    using templates in templates

    John Harrison, Jul 31, 2003, in forum: C++
    Replies:
    8
    Views:
    405
    Torsten Curdt
    Jul 31, 2003
  3. JKop
    Replies:
    3
    Views:
    526
  4. Tom McCallum

    Templates within templates

    Tom McCallum, Aug 4, 2004, in forum: C++
    Replies:
    2
    Views:
    382
    tom_usenet
    Aug 4, 2004
  5. recover
    Replies:
    2
    Views:
    863
    recover
    Jul 25, 2006
Loading...

Share This Page