Re: Incomplete types and std::vector
On Feb 6, 6:07 am, Joshua Maurice <joshuamaur...@gmail.com> wrote:
On Feb 5, 1:21 pm, "Leigh Johnston" <le...@i42.co.uk> wrote:
"Juha Nieminen" <nos...@thanks.invalid> wrote in message
My 2 cents: Generally when I use pimpl, it's
//header
#include <string>
class Foo
{
public:
Foo();
~Foo();
std::string getName() const; //ex func
//etc.
private:
class FooImpl;
FooImpl * impl;
};
//cpp
class Foo::FooImpl
{
public:
//impl
};
Foo::Foo() : impl(new Foo::FooImpl) {}
Foo::~Foo() { delete impl; }
std::string Foo::getName() const { /*return impl->getName();*/ return
"";
}
//end example
Most uses of pimpl are as simple as this.
That's how Herb Sutter defined it, and since he invented the
term, I think it just adds to the confusion if you decide to use
some other definition. (It's not a term like OO, which already
has hundreds of subtly different definitions.)
I would be skeptical of a design which had "multiple pimpl
pointers". The constructor body of Foo is generally that, no
more, no less, give or take the names. However, I suppose
there's nothing to lose by using std::auto_ptr either.
Except for an additional include in the header, no. And perhaps
a false sense of security; typically, when you use auto_ptr in
an object, you don't need to provide a user defined destructor.
Finally, I feel stupid. Could someone explain to me how this
works, how std::auto_ptr::~auto_ptr "finds" the name Foo as a
complete type? Probably something to do with template lookup
rules, the two phase lookup, lookup based on instantiation
context and declaring context, and the rest of that nastiness.
Playing around with it, I proved to myself that it does work
if Foo::~Foo is defined in a scope where FooImpl is a complete
type, and that it deletes it as an incomplete type if
Foo::~Foo is declared in a different translation unit.
I would think that it would be undefined behavior if Foo::~Foo
is defined in a scope where FooImpl is an incomplete type.
In fact, it's undefined behavior if the class is even
instantiated in a context where Foo is not complete. I wouldn't
be surprised if some implementations complained.
Interestingly enough, if I move the Foo::~Foo definition to
before the FooImpl class definition in the same translation
unit, a scope where FooImpl is an incomplete type, visual
studios 2008 still deletes it as a complete type, which
completely mystifies me. Is this visual studios protecting me
from myself, and making it "do the right thing" in a case of
undefined behavior? Or do I completely fail at understanding
the template instantiation and name lookup rules?
It's undefined behavior; in practice, it will depend on how the
compiler instantiates templates.
--
James Kanze