How to transfer QPainter? (move an object from a factory function)

530 Views Asked by At

In a Qt-related code I tried to reduce some duplicated lines by the following method:

QPainter createPainter(const QColor& color)
{
  QPainter painter(&m_image);
  painter.setBrush(color);
  painter.setPen(color);
  return painter;
}

But QPainter's copy ctor is explicitly deleted. It should be not not problem in c++11, but sadly it is neither moveable. Is it any reason for this or is it just an API defect? Is it a good solution for createPainter (except providing move-ctor)?

  • It could accept a QPainter reference, but this would decrease the meaning of the method, and would add noise to the caller's code.
  • It could return a unique_ptr to the QPainter, but it would introduce overhead for heap-allocation.
  • ... Any other ideas?

Thanks for your responses!

2

There are 2 best solutions below

15
On BEST ANSWER

One trick is to return by constant reference:

Option 1:

QPainter createPainter(const QColor& color) //definitely return by value
{
  QPointer painter(&m_image);
  painter.setBrush(color);
  painter.setPen(color);
  return painter;
}

Then do this:

const QPainter& painter = createPainter(const QColor& color);

By the C++ standard, this guarantees that no copying will happen, but the return value's life will be extended.

Option 2:

User shared or unique pointers. I know you said they have an overhead, but that's nothing, assuming you're not developing game engines and this is the main pipeline (and I'm sure you're not using Qt in such a game engine).

Option 3:

If none of these make you happy, I'll suggest the solution that I hate, just for completeness. Use macros!

#define CreatePainter(painter_name) \
QPointer painter_name(&m_image);    \
painter_name.setBrush(color);       \
painter_name.setPen(color);      

To use it:

CreatePainter(painter);
painter.begin(); 
//...

EDIT:

Option 4: I just learned (thanks to Quentin) that this is legal:

QPainter createPainter(const QColor& color) //definitely return by value
{
  QPointer painter(&m_image);
  painter.setBrush(color);
  painter.setPen(color);
  return painter;
}

Then this:

QPainter&& painter = createPainter(const QColor& color);

Check the reference here. It's a new C++11 solution to extend an object's life-time without making it const.

0
On

Just as idea

struct ColoredPainter : public QPainter {
ColoredPainter (device, color) : QPainter (device)
setBrush(color);
setPen(color);
};

...

ColoredPainter painter(m_Image, color);

But I don't like that idea. Looks like duplicated code parts just looks the same but it makes no sense to put it to standalone block. It will be hard to understand this kind of class or even function.