windows - Is it valid for a C++ compiler to implicitly instantiate ALL member functions of a template class? -
suppose have public class , private implementation class (e.g. pimpl pattern), , wish wrap private class template smart pointer class checked delete, follows:
publicclass.h
class privateclass; // simple smart pointer checked delete template<class x> class demo_ptr { public: demo_ptr (x* p) : the_p(p) { } ~demo_ptr () { // boost::checked_delete: don't allow compilation of incomplete type typedef char type_must_be_complete[ sizeof(x)? 1: -1 ]; (void) sizeof(type_must_be_complete); delete the_p; } private: x* the_p; }; // public-facing class wishes wrap private implementation guts class publicclass { public: publicclass(); ~publicclass(); private: demo_ptr<privateclass> pvt; };
publicclass.cpp
#include "publicclass.h" class privateclass { public: // implementation stuff goes here... privateclass() {} }; //--------------------------------------------------------------------------- publicclass::publicclass() : pvt(new privateclass()) {} publicclass::~publicclass() {}
main.cpp
#include "publicclass.h" int main() { publicclass *test = new publicclass(); delete test; return 0; }
this code compiles on visual c++ 2008, fails compile on old version of c++ builder. in particular, main.cpp
not compile because demo_ptr<privateclass>::~demo_ptr
being instantiated main.cpp
, , destructor won't compile because can't sizeof
on incomplete type privateclass
. clearly, not useful compiler instantiating ~demo_ptr
in consuming main.cpp
, since never able generate sensible implementation (seeing how ~privateclass
not accessible). (publicclass.cpp
compiles fine on tested compilers.)
my question is: c++ standard implicit instantiation of template class's member functions? might 1 of following? in particular, has changed on years?
- if template class used, member functions of class should implicitly instantiated - whether used or not?
- or: template class functions should implicitly instantiated 1 @ time if used. if particular template class function isn't used, shouldn't implicitly instantiated - if other template class functions used , instantiated.
it seems clear second case case today because same pattern used pimpl , unique_ptr
checked delete, maybe not case in past? first case acceptable compiler behavior in past?
or in other words, compiler buggy, or did accurately follow c++98 standard, , standard changed on years?
(fun fact: if remove checked delete in c++ builder, , have function inlining turned off, project happily compile. publicclass.obj
contain correct ~demo_ptr
implementation, , main.obj
contain incorrect ~demo_ptr
implementation undefined behavior. function used depend on order in these files fed linker.)
update: due compiler bug, noted andy prowl, still not fixed in c++ builder xe8. i've reported bug embarcadero: bcc32 compiler causes undefined behavior when using std::auto_ptr pimpl idiom because template instantiation rules not follow c++ spec
if template class used, member functions of class should implicitly instantiated - whether used or not?
no, not case. per paragraph 14.7.1/10 of c++11 standard (and paragraph 14.7.1/9 of c++03 standard) specifies:
an implementation shall not implicitly instantiate function template, member template, non-virtual member function, member class, or static data member of class template not require instantiation.
as when instantiation required, paragraph 14.7.1/2 specifies:
unless member of class template or member template has been explicitly instantiated or explicitly specialized, specialization of member implicitly instantiated when specialization referenced in context requires member definition exist; [...]
this not case if member function never referenced.
unfortunately, can't provide official reference on rules before c++03, best of knowledge same "lazy" instantiation mechanism adopted in c++98.
Comments
Post a Comment