c++ - Pimpl with smart pointers in a class with a template constructor: weird incomplete type issue -
when using smart pointers pimpl idiom, in
struct foo { private: struct impl; boost::scoped_ptr<impl> pimpl; };
the obvious problem foo::impl
incomplete @ point destructor of foo
generated.
compilers emit warning there, , boost::checked_delete
, used internally boost smart pointers, statically asserts class foo::impl
complete , triggers error if not case.
for above example compile, 1 therefore must write
struct foo { ~foo(); private: struct impl; boost::scoped_ptr<impl> pimpl; };
and implement empty foo::~foo
in implementation file, foo::impl
complete. advantage of smart pointers on bare pointers, because can't fail implement destructor.
so far, good. came across weird behaviour when try introduce template constructor in similar bar
class (full code, please try yourself):
// file bar.h #ifndef bar_h #define bar_h 1 #include <vector> #include <boost/scoped_ptr.hpp> struct bar { template <typename i> bar(i begin, end); ~bar(); private: struct impl; boost::scoped_ptr<impl> pimpl; void buildimpl(std::vector<double>&); }; template <typename i> bar::bar(i begin, end) { std::vector<double> tmp(begin, end); this->buildimpl(tmp); } #endif // bar_h // file bar.cpp #include "bar.h" struct bar::impl { std::vector<double> v; }; void bar::buildimpl(std::vector<double>& v) { pimpl.reset(new impl); pimpl->v.swap(v); } bar::~bar() {} // file foo.h #ifndef foo_h #define foo_h 1 #include <boost/scoped_ptr.hpp> struct foo { foo(); ~foo(); private: struct impl; boost::scoped_ptr<impl> pimpl; }; #endif // foo_h // file foo.cpp #include "foo.h" struct foo::impl {}; foo::foo() : pimpl(new impl) {} foo::~foo() {} // file main.cpp #include "foo.h" #include "bar.h" int main() { std::vector<double> v(42); foo f; bar b(v.begin(), v.end()); }
when compiling example visual studio 2005 sp1, error bar
not foo
:
1>compiling... 1>main.cpp 1>c:\users\boost_1_45_0\boost\checked_delete.hpp(32) : error c2027: use of undefined type 'bar::impl' 1> c:\users\visual studio 2005\projects\checkeddeletetest\checkeddeletetest\bar.h(15) : see declaration of 'bar::impl' 1> c:\users\boost_1_45_0\boost\smart_ptr\scoped_ptr.hpp(80) : see reference function template instantiation 'void boost::checked_delete<t>(t *)' being compiled 1> 1> [ 1> t=bar::impl 1> ] 1> c:\users\boost_1_45_0\boost\smart_ptr\scoped_ptr.hpp(76) : while compiling class template member function 'boost::scoped_ptr<t>::~scoped_ptr(void)' 1> 1> [ 1> t=bar::impl 1> ] 1> c:\users\visual studio 2005\projects\checkeddeletetest\checkeddeletetest\bar.h(16) : see reference class template instantiation 'boost::scoped_ptr<t>' being compiled 1> 1> [ 1> t=bar::impl 1> ] 1>c:\users\boost_1_45_0\boost\checked_delete.hpp(32) : error c2118: negative subscript 1>c:\users\boost_1_45_0\boost\checked_delete.hpp(34) : warning c4150: deletion of pointer incomplete type 'bar::impl'; no destructor called 1> c:\users\visual studio 2005\projects\checkeddeletetest\checkeddeletetest\bar.h(15) : see declaration of 'bar::impl'
i try recent gcc home.
i don't understand going on: @ point destructor defined (ie. in bar.cpp
), definition of bar::impl
available, there should not problem. why work foo
, not bar
?
what missing here ?
this destructor of boost::shared_ptr<>
requires object complete when using boost::checked_deleter<>
deleter. because put range constructor bar::bar(i begin, end)
in header file compiler must generate code destroys constructed members if constructor throws, hence trying instantiate boost::scoped_ptr<t>::~scoped_ptr(void)
when instantiating template constructor.
it less useful use smart pointers pimpl. since need provide destructor anyway, put delete pimpl
in destructor , done that.
Comments
Post a Comment