Hi! I'm having trouble implementing Pimpl idiom with Qt. Look at the following code: class IndispFilterWidget : public QHBox { Q_OBJECT public: IndispFilterWidget(QWidget* parent = 0); private: struct Private; boost::scoped_ptr<Private> d; }; struct IndispFilterWidget::Private { QIntDict<BrushButton> buttons; }; IndispFilterWidget::IndispFilterWidget(QWidget* parent) : QHBox(parent) , d(new Private) { } and see the error: /usr/include/boost/checked_delete.hpp: In function 'void boost::checked_delete(T*) [with T = exames::calendario::IndispFilterWidget::Private]': /usr/include/boost/scoped_ptr.hpp:77: instantiated from 'boost::scoped_ptr<T>::~scoped_ptr() [with T = exames::calendario::IndispFilterWidget::Private]' /home/fsousa/projects/GAL/BUILD/modules/exames/calendario/../../../../modules/exames/calendario/IndispFilterWidget.h:31: instantiated from here /usr/include/boost/checked_delete.hpp:32: error: invalid application of 'sizeof' to incomplete type 'exames::calendario::IndispFilterWidget::Private' /usr/include/boost/checked_delete.hpp:32: error: creating array with size zero ('-0x000000001') /usr/include/boost/checked_delete.hpp:33: error: invalid application of 'sizeof' to incomplete type 'exames::calendario::IndispFilterWidget::Private' /usr/include/boost/checked_delete.hpp:33: error: creating array with size zero ('-0x000000001') /usr/include/boost/checked_delete.hpp:34: warning: possible problem detected in invocation of delete operator: /usr/include/boost/checked_delete.hpp:29: warning: 'x' has incomplete type /home/fsousa/projects/GAL/BUILD/modules/exames/calendario/../../../../modules/exames/calendario/IndispFilterWidget.h:45: warning: forward declaration of 'struct exames::calendario::IndispFilterWidget::Private' If I remove Q_OBJECT macro or add a destructor the code compiles fine. I don't have a problem with shared_ptr, only with scoped_ptr. -- Filipe Sousa
Hello Filipe, Tuesday, May 17, 2005, 5:46:27 PM, you wrote:
Hi!
I'm having trouble implementing Pimpl idiom with Qt.
If I remove Q_OBJECT macro or add a destructor the code compiles fine. I don't have a problem with shared_ptr, only with scoped_ptr.
If you wish to use scoped_ptr as a pointer to implementation you should always define (in .cpp file) destructor for outer class even if it is empty destructor. This allows compiler to generate (instantiate) proper destructor for shared_ptr<YourImplementationClass>. Otherwise it instantiates such destructor in scope where YourImplementationClass is incomplete and you receive said errors. It is normal common practice to define empty constructor in such cases. shared_ptr does not have problem like this, but it is more "heavyweight". -- Best regards, Vladimir mailto:vkrasovsky@yandex.ru
Filipe Sousa wrote:
Hi!
I'm having trouble implementing Pimpl idiom with Qt. Look at the following code:
class IndispFilterWidget : public QHBox { Q_OBJECT public: IndispFilterWidget(QWidget* parent = 0);
private: struct Private; boost::scoped_ptr<Private> d; };
struct IndispFilterWidget::Private { QIntDict<BrushButton> buttons; };
IndispFilterWidget::IndispFilterWidget(QWidget* parent) : QHBox(parent) , d(new Private) { }
and see the error:
/usr/include/boost/checked_delete.hpp: In function 'void boost::checked_delete(T*) [with T = exames::calendario::IndispFilterWidget::Private]': /usr/include/boost/scoped_ptr.hpp:77: instantiated from 'boost::scoped_ptr<T>::~scoped_ptr() [with T = exames::calendario::IndispFilterWidget::Private]' /home/fsousa/projects/GAL/BUILD/modules/exames/calendario/../../../../modules/exames/calendario/IndispFilterWidget.h:31: instantiated from here /usr/include/boost/checked_delete.hpp:32: error: invalid application of 'sizeof' to incomplete type 'exames::calendario::IndispFilterWidget::Private' /usr/include/boost/checked_delete.hpp:32: error: creating array with size zero ('-0x000000001') /usr/include/boost/checked_delete.hpp:33: error: invalid application of 'sizeof' to incomplete type 'exames::calendario::IndispFilterWidget::Private' /usr/include/boost/checked_delete.hpp:33: error: creating array with size zero ('-0x000000001') /usr/include/boost/checked_delete.hpp:34: warning: possible problem detected in invocation of delete operator: /usr/include/boost/checked_delete.hpp:29: warning: 'x' has incomplete type /home/fsousa/projects/GAL/BUILD/modules/exames/calendario/../../../../modules/exames/calendario/IndispFilterWidget.h:45: warning: forward declaration of 'struct exames::calendario::IndispFilterWidget::Private'
If I remove Q_OBJECT macro or add a destructor the code compiles fine. I don't have a problem with shared_ptr, only with scoped_ptr.
scoped_ptr cannot be used with incomplete types, unfortunately, and thus is not available for use in the pimpl idiom. You can: 1. Use shared_ptr. 2. Use a regular pointer and delete it in the class destructor (in the implementation file). 3. Not much else you can do. Write your own incomplete_scoped_ptr, maybe. :o)
Hello Arne, Wednesday, May 18, 2005, 7:38:20 PM, you wrote:
scoped_ptr cannot be used with incomplete types, unfortunately, and thus is not available for use in the pimpl idiom.
Please read http://www.boost.org/libs/smart_ptr/scoped_ptr.htm . Near the end of page you can see "One common usage of scoped_ptr is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file." Examples are also there. -- Best regards, Vladimir mailto:vkrasovsky@yandex.ru
Vladimir Krasovsky wrote:
Hello Arne,
scoped_ptr cannot be used with incomplete types, unfortunately, and thus is not available for use in the pimpl idiom.
Please read http://www.boost.org/libs/smart_ptr/scoped_ptr.htm . Near the end of page you can see "One common usage of scoped_ptr is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file."
Examples are also there.
Hello Vladimir, I stand corrected. So it's actually not "scoped_ptr cannot be used with incomplete types" but "scoped_ptr's destructor cannot be instantiated with incomplete types". So class UsingPimpl { private: struct Impl; boost::scoped_ptr<Impl> impl; public: UsingPimpl(); void doSomething(); }; won't work, but by adding UsingPimpl's destructor declaration (to inhibit automatic generation) to the definition of UsingPimpl, and the destructor's definition (after UsingPimpl::Impl has been defined) to the implementation file, it can be made to work. Thanks a lot, Arne Vogel
Hello Arne, Thursday, May 19, 2005, 2:10:04 PM, you wrote:
I stand corrected. So it's actually not "scoped_ptr cannot be used with incomplete types" but "scoped_ptr's destructor cannot be instantiated with incomplete types".
That's correct. :) -- Best regards, Vladimir mailto:vkrasovsky@yandex.ru
participants (3)
-
Arne Vogel
-
Filipe Sousa
-
Vladimir Krasovsky