Search code examples
c++qtc++11move-semanticsqpainter

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


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!


Solution

  • 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.