Board index » cppbuilder » auto_ptr to incomplete type

auto_ptr to incomplete type


2004-02-06 10:27:16 PM
cppbuilder60
I believe I have found a solution to Borland Builder's problematic
handling of auto_ptr members.
Consider the following files (this can integrated into a VCL
application):
// in file MyClass.h
class MyClass
{
public:
~MyClass();
};
// in file MyClass.cpp
MyClass::~MyClass()
{
ShowMessage("MyClass dtor");
}
// in file MyClassClient.h
#include <memory>
class MyClass;
class MyClassClient
{
public:
MyClassClient();
private:
std::auto_ptr<MyClass>_myClass_ap;
};
// in file MyClassClient.cpp
#include "MyClass.h"
MyClassClient::MyClassClient()
: _myClass_ap(new MyClass)
{}
// now in the button click handler on some form
void TForm1::Button1Click()
{
MyClassClient myClassClient;
}
If you've read this far it means you know that the call to
ShowMessage("MyClass dtor") will never happen.
The rules for cplusplus require that the destructor to MyClassClient
be written AFTER the inclusion of MyClass.h
So you rewrite MyClassClient.h as follows:
#include <memory>
class MyClass;
class MyClassClient
{
public:
MyClassClient();
~MyClassClient(); // add an explicit dtor
private:
std::auto_ptr<MyClass>_myClass_ap;
};
and then rewrite MyClassClient.cpp:
#include "MyClass.h"
MyClassClient::MyClassClient()
: _myClass_ap(new MyClass)
{}
MyClassClient::~MyClassClient()
{
// this explicit dtor appears after MyClass has been declared in
full.
}
If you had a nice bug-free compiler this would be all you had to do.
But you're using Borland Builder so you have a bug and ShowMessage
still doesn't get called.
Assuming you're using the IDE, goto the Project menu and select
Options. Now switch to the Compiler tab and uncheck Disable inline
expansions.
Rerun and, as if by magic, the Message box will appear!
I haven't examined the reason for this but the dtor for auto_ptr is
inline...
Unfortunately all your inlines are now inline so step-debugging will
be a bit strange. And if you like to use the "Debug" and "Release"
shortcut buttons in Project Options you will have keep clearing this
check box.
Perhaps there's a #pragma to but around ~auto_ptr to always have it
inlined? I haven't looked into this.
If this is all to much hassle, replace all instances of auto_ptr with
boost::shared_ptr (unless you really really can't afford the overhead)
--- slight change of subject now ---
There's something in the cplusplus standard along this lines of 'You
can't instantiate an STL template class with an incomplete class type'
I don't have a copy of the standard so I can't quote it accurately.
I take this to mean you can't do this:
class MyClass;
std::vector<MyClass>vector;
std::list<MyClass>list;
This is fair enough as both vector and list need to know the size (and
hence the complete type) of MyClass in order to create vectors and
lists.
Some people think you should apply this rule to auto_ptrs too:
class MyClass;
std::auto_ptr<MyClass>myClass_ap // some say this isn't allowed.
Well, my own interpretation is that you're really just specifying what
kind of pointer you want. As we all know a pointer (even a pointer to
an incomplete type) is built-in and as such is never incomplete. So
this is perfectly legal.
I hope this is helpful to someone.
 
 

Re:auto_ptr to incomplete type

Quote
It's not just BCB.
Yes it is.
This post does not refer to the general problem of using auto_ptr
members on any old cpp compiler.
This post refers to BCB's inability to cope with a solution that
should work. More specifically, it shows which option to change to get
BCB to behave correctly in this situation.
I think you gave up halfway through my original post and assumed I was
referring to the general case.
 

Re:auto_ptr to incomplete type

On 6 Feb 2004 06:27:16 -0800, XXXX@XXXXX.COM (David
Webster-Jaggard) wrote:
Quote
I believe I have found a solution to Borland Builder's problematic
handling of auto_ptr members.
The rules for cplusplus require that the destructor to MyClassClient
be written AFTER the inclusion of MyClass.h
Right - if you define the destructor explicitly, the point of
instantiation of auto_ptr<MyClass>::~auto_ptr() (which requires
MyClass to be complete) is directly after the destructor definition.
Quote
#include "MyClass.h"

MyClassClient::MyClassClient()
: _myClass_ap(new MyClass)
{}

MyClassClient::~MyClassClient()
{
// this explicit dtor appears after MyClass has been declared in
full.
}
Instantiation point of auto_ptr<MyClass>::~auto_ptr() is here, so
MyClass is complete and all should be fine.
Quote

If you had a nice bug-free compiler this would be all you had to do.
Right.
Instead of defining the destructor, try placing an explicit
instantiation of std::auto_ptr<MyClass>::~auto_ptr where you were
going to put the destructor definition:
template std::auto_ptr<MyClass>::~auto_ptr();
Depending on the intricacies of borland's inlining and template
instantiation merging model, etc., that might fix things.
Quote
Some people think you should apply this rule to auto_ptrs too:
class MyClass;
std::auto_ptr<MyClass>myClass_ap // some say this isn't allowed.
The standard doesn't explicitly forbid it.
Quote
Well, my own interpretation is that you're really just specifying what
kind of pointer you want. As we all know a pointer (even a pointer to
an incomplete type) is built-in and as such is never incomplete. So
this is perfectly legal.
Yes, but you are far better off using a smart pointer designed for use
with incomplete types, rather that one that requires explicit
intervention (by providing a destructor definition, etc.). The classic
example is boost::shared_ptr (soon to be std::shared_ptr) - the other
poster mentioned grin_ptr, I have a couple of implementations{*word*154}
around too. auto_ptr is not intended for use as a member variable - it
is really only designed to exist as an automatic variable to aid
exception safety.
Tom
C++ FAQ: www.parashift.com/c++-faq-lite/
C FAQ: www.eskimo.com/~scs/C-faq/top.html
 

{smallsort}

Re:auto_ptr to incomplete type

A rant:
The whole point of this flippin' post was to point out that the
flippin' bug in BCB could be worked-around by flipping a flippin'
switch in the flippin' compiler options.
Perhaps it was a mistake to include a flippin' example (just trying to
make sure everyone new what I was flippin' on about) as this seems to
have led the two flippin' respondees to assume it was a request for
some flippin' help with flippin' auto_ptrs when I know full well how
flippin' auto_ptrs work.
Bob missed the flippin' point entirely after reading about 3 flippin'
lines of the my post.
Tom also missed the flippin' point as he read the whole post but read
it too flippin' fast. Had he slowed down he would have noticed I
mentioned flippin' boost::shared_ptrs...
This sort of of thing seems to happen to everyone who submits a post.
Everyone has to get their flippin' bit in whether or not it has any
flippin' bearing on the original post. Or worse, the first responder
solves the flippin' problem (if there was one) and is followed up by
300 flippin' idiots all reiterating the same flippin' information
because they seem to think it flippin' matters that they new what the
flippin' answer was too.
Its a good job I didn't use my real flippin' name on here or I'd be
right in the flippin' Eartha Kitt.
Oh flip. Flippin' Kangaroos nicked my flippin' car and speeding down
the flippin' road in it...
 

Re:auto_ptr to incomplete type

On 12 Feb 2004 02:43:08 -0800, XXXX@XXXXX.COM (David
Webster-Jaggard) wrote:
[SNIP most of rant]
Quote
Tom also missed the flippin' point as he read the whole post but read
it too flippin' fast. Had he slowed down he would have noticed I
mentioned flippin' boost::shared_ptrs...
Hmm, I did miss that, but I was just pointing out a few issues
relating to your post:
1: auto_ptr wasn't really designed to be used as a member variable,
ignoring compiler bugs for a moment - it's just too easy to trigger
silent undefined behaviour. If you came across the bug/solution in
some other context, then fine.
2: I suggested an alternative solution to playing with compiler
switches (explicit instantiation). Did you try it? Does it work?
3: "I haven't examined the reason for this but the dtor for auto_ptr
is inline..."
I attempted to suggest that the reason was due to the misplacing of
the auto_ptr::~auto_ptr destructor instantiation. Explicit
instantiation may solve this.
Quote
Its a good job I didn't use my real flippin' name on here or I'd be
right in the flippin' Eartha Kitt.
You mean "David Webster-Jaggard" isn't your real name!? :)
Tom Usenet
C++ FAQ: www.parashift.com/c++-faq-lite/
C FAQ: www.eskimo.com/~scs/C-faq/top.html