What I really wanted was a single class, ImageSegmentation<T> that operates on images of type T. The problem was that this object needed to be a member of my Qt form object (called Form), but I didn't know T until runtime (the user selects which type of image to operate on. Because of that, I structured it like this:

ImageSegmentationBase - functions that don't depend on T
ImageSegmentation<T> : public ImageSegmentationBase - function which depend on T.

Then I member variable of Form:

ImageSegmentationBase* MyImageSegmentation;

I instantiate it with

MyImageSegmentation = new ImageSegmentation<T>;

The problem now is that I can't get the data out! From a function Form::function() I want to do:

Form::function()
{
T image = MyImageSegmentation->GetData();
... continue processing image normally...
}

Of course GetData can't be defined in ImageSegmentationBase because the return type is T. It can be defined no problem in ImageSegmentation<T>, but I don't know T inside Form::function()!

I tried to put a typedef inside ImageSegmentationBase:

template<class T>
struct ImageSegmentationBase{
  typedef T type;
};

To then do

Form::function()
{
MyImageSegmentation::type image = MyImageSegmentation->GetData();
}

but it says "ImageSegmentation is not a namespace".

Is there a way to do something like this? It seems like a pretty standard pattern, no?

Thanks,

David

Recommended Answers

All 8 Replies

The problem is easily solved by throwing type safety out the door:

class Base {
public:
    virtual void GetData(void *data) = 0;
};

template <typename T>
class Derived: public Base {
    int _data;
public:
    Derived(int data): _data(data) {}

    virtual void GetData(void *data)
    {
        *(int*)data = _data;
    }
};

#include <iostream>

int main()
{
    Base *p = new Derived<int>(123);
    int data;

    p->GetData(&data);

    std::cout<< data <<'\n';
}

But this seems more of a fundamental design issue to me. Maybe if you take a few steps back and come up with a different solution, you can sidestep the issue entirely. Do all of your image types relate? Perhaps a dash of polymorphism there could clean things up.

Hm, yea that would work, but as you said doing it like that makes it look like I'm doing it wrong!

Assume the image types did relate - that is, that they are all Image<N> where N is the number of channels (1 for grayscale, 3 for RGB, etc). How would this change anything? Since N is not known until runtime, I have the same problem as before, right?

I'm definitely up for a good redesign, but this was the only way I knew to even get it to work at all (before this problem). Do you have any suggestions? I thought what I was doing was already 'polymorphism'?

Thanks,

David

but as you said doing it like that makes it look like I'm doing it wrong!

I said nothing of the sort. While you'd need to defend that particular decision in a code review, practical programming isn't always pretty and elegant.

How would this change anything?

I was thinking ditching templates and using inheritance:

class ImageType;
class Grayscale: public ImageType;
class RGB: public ImageType;

class ImageSegmentationBase {
    //...
public:
    //...
    virtual ImageType& GetData() = 0;
    //...
};

ImageSegmentation overrides GetData to return the suitable child of ImageType, and from there you have more options in terms of accessing the object.

Ah I see, that makes sense if it was my own image class. However, I am using an already-templated Image class. I was thinking I could just wrap it, but it needs the template argument! If we call it TheirImage, I would want something like:

class MyImage : public TheirImage
{
// implement nothing
};

class MyRGBImage : public MyImage
{
// how to specify that it is a 3 channel image?
};

but it would of course complain that TheirImage needs the template parameter (i.e. TheirImage<N>). Any suggestions?

David

Composition?

class MyImage;

class MyRGBImage: public MyImage {
    TheirImage<3> _image;
    //...
};

So it would be more of an ImageContainer class? Because everything I did would now become

DoSometing(ImageConainter.image)

where it used to just be

DoSomething(image)

That is what you're suggesting, correct?

So it would be more of an ImageContainer class?

More of a facade pattern. You're taking the awkward interface provided and converting it into something better suited for your design. You could also potentially overload the conversion operator to avoid the ImageContainer.image construct if you find it ugly.

Just a thought. You could also use the Boost.Variant to solve your problem. Just return a boost::variant with all the possible image types. It's not pretty, but it'll work. Still better than violating type safety. If your image types are comparable in size, it might be a good alternative.

Personally, I think you ought to first take a step back and think of a redesign to avoid this problem altogether. The adaptor pattern and visitor pattern are usually useful when trying to pull external and poorly integrated code into your framework. Which is basically what Narue has already proposed. As an adaptor, you could code your own class that can contain and deal with any of the types of images you have (sort-of like a special purpose boost::variant class). As a visitor concept, you could isolate what transformations you need on the images and code a visitor class that can perform these transformations in a way that is tailored to each type, then all you need is a dummy base class for the image, use the RTTI to identify the type, and dispatch it to an appropriate visitor (this could be done with a MACRO or maybe in a Boost.Bind-like way).

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.