2

Context

I am learning C++ with Qt at home. I am using the project to learn design practices. Recently I came across a need that led me to templates.

I created an openGL picture viewer for Qt's QPixmap picture format. I want to add a picture format converter into this viewer.

My need

At the moment my need is to convert openCV's cv::Mat into QPixmap. In the future I could encounter other formats (so other C++ types). So I thought to templates. Here is my starting point:

template <class T>
class ToQPixmapConverter : public QObject
{
public:
    ToQPixmapConverter(QObject *parent = 0) : QObject(parent) {
        setRawPic(new T());
    }
    ~ToQPixmapConverter(){delete rawPic;}

    T *getRawPic() const {return rawPic;}
    void setRawPic(T *pRawPic) {rawPic = pRawPic;}

    // TO BE SPECIALIZED/OVERLOADED or something
    QPixmap *convert(T &pRawPic) {return nullptr;}
    QPixmap *convertFromPath(cv::String const path) {return nullptr;}

protected:
    T* rawPic;
    QPixmap localPixMap;
};

I want to keep all members and most methods as is, so I only have to implement convert and convertFromPath for all different formats.

My failed attempts

Partial template specialization. I struggled a long time trying stuff that is not permitted and finally I found this solution : Understanding (simple?) C++ Partial Template Specialization

But in the second answer:

Explicitly specializing functions is never (almost never?) the right way. In my work as a programmer, I've never explicitly specialized a function template. Overloading and partial ordering is superior.

Inheriting from the class template. I think that is what I need but I can't make it happen:

class CvMatToQPixmapConverter : public ToQPixmapConverter<cv::Mat>{};

QPixmap * CvMatToQPixmapConverter::convert(cv::Mat &pRawPic)
{
    // Some stuff
}

QPixmap * CvMatToQPixmapConverter::convertFromPath(cv::String const path)
{
    // Some stuff
}

With this code I get:

error: no 'QPixmap* CvMatToQPixmapConverter::convert(cv::Mat&)' member function declared in class 'CvMatToQPixmapConverter'
 QPixmap * CvMatToQPixmapConverter::convert(cv::Mat &pRawPic)
                                                            ^

So I tried to define ToQPixmapConverter<cv::Mat> before:

template <>
class ToQPixmapConverter<cv::Mat>;

But I get:

error: invalid use of incomplete type 'class ToQPixmapConverter<cv::Mat>'
 class CvMatToQPixmapConverter : public ToQPixmapConverter<cv::Mat>{};
                                        ^

Help needed!

I hope I gave enough context so that someone could help me. Basically, my questions are.

  1. How do yo fix the last piece of code?
  2. Is the recommended solution for this kind of problems?

Thank you for your help! :)

PS: My initial idea was to combine the strategy pattern with a class template... But I failed. Would it work here?

Community
  • 1
  • 1
Plouff
  • 3,290
  • 2
  • 27
  • 45

1 Answers1

2

I think an abstract base class and the necessary concrete sub-classes will be a better design for you instead of a class template.

class ToQPixmapConverter : public QObject
{
   public:
      ToQPixmapConverter(QObject *parent = 0) : QObject(parent) {}
      ~ToQPixmapConverter(){}

      // TO BE OVERLOADED
      virtual QPixmap *convert() {return nullptr;}
      virtual QPixmap *convertFromPath(cv::String const path) {return nullptr;}

   protected:
}

class FromCVMatToQPixmapConverter : public ToQPixmapConverter
{
   public:
      FromCVMatToQPixmapConverter(cv::Mat* rawPicIn, QObject *parent = 0) : ToQPixmapConverter(parent), rawPic(rawPicIn) {}
      ~FromCVMatToQPixmapConverter(){delete rawPic;}

      virtual QPixmap *convert() { /* Add code to do it*/ }
      virtual QPixmap *convertFromPath(cv::String const path) { /* Add code to do it*/ }
   private:
      cv::Mat* rawPic;
};
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thank you for your answer! I wanted to store `rawPic` in the base class/template and that led me to those complicated implementations. But actually I don't think this is so useful. And thanks to your solution I see how I could use the strategy pattern if needed. Thanks again! – Plouff Apr 07 '15 at 20:07