J
JackC
Hi
Problem:
I wish to use a pimpl to hide implementation/storage of a class (T), but I
also want to hold objects of that class (T) in an std::vector<T> (or
similar). T is non trivial (i.e. not POD, because it has std::string and
other classes requiring proper destruction, although all drill down to POD
and strings eventually).
Classic code layout:
Header file:
class T {
public:
....
T();
~T();
private:
typedef struct Impl; //opaque, incomplete type
std::auto_ptr<Impl> pimpl; // see below
};
Source file:
struct T::Impl {
Impl() {} // called on construction
~Impl() {} // should be called on T going out of scope, see below
};
T::T : pimpl (new Impl) {}
T::~T() // this is called on a T going out of scope
auto_ptr will not do because: (a) as in classic text (Herb Sutter's
Exceptional C++) the type of Impl is incomplete, and thus the compiler is at
liberty to provide undefined behaviour for destruction of Impl (Borland's
solution is to generate (another) empty destructor for T::Impl), (b)
auto_ptr does not provide the correct copy behaviour for STL containers.
I cannot easily determine a way forward; I tried using Alan Griffith's
grin_ptr (http://www.octopull.demon.co.uk/arglib/TheGrin.html) but removing
the copy and assignment operators - this fixed problem with destruction, but
not with storing T in the STL container as do so sort operations the compile
fails. The original grin_ptr had deep and shallow cloning and I was not
sure what to do. The issue is what must be provided for success in both
areas, and is there any code out there that will do the job as I do not want
to re-invent the wheel.
NB I looked into Boost but found it hard (impossible) to work out how to
correctly install on my WinXP m/c using Borland's C++ Builder 6.0 (or for
that matter BCC5.5). Even then I cannot be sure that the smart pointers
provided are suitable.
Regards
Jack Sharman
Problem:
I wish to use a pimpl to hide implementation/storage of a class (T), but I
also want to hold objects of that class (T) in an std::vector<T> (or
similar). T is non trivial (i.e. not POD, because it has std::string and
other classes requiring proper destruction, although all drill down to POD
and strings eventually).
Classic code layout:
Header file:
class T {
public:
....
T();
~T();
private:
typedef struct Impl; //opaque, incomplete type
std::auto_ptr<Impl> pimpl; // see below
};
Source file:
struct T::Impl {
Impl() {} // called on construction
~Impl() {} // should be called on T going out of scope, see below
};
T::T : pimpl (new Impl) {}
T::~T() // this is called on a T going out of scope
auto_ptr will not do because: (a) as in classic text (Herb Sutter's
Exceptional C++) the type of Impl is incomplete, and thus the compiler is at
liberty to provide undefined behaviour for destruction of Impl (Borland's
solution is to generate (another) empty destructor for T::Impl), (b)
auto_ptr does not provide the correct copy behaviour for STL containers.
I cannot easily determine a way forward; I tried using Alan Griffith's
grin_ptr (http://www.octopull.demon.co.uk/arglib/TheGrin.html) but removing
the copy and assignment operators - this fixed problem with destruction, but
not with storing T in the STL container as do so sort operations the compile
fails. The original grin_ptr had deep and shallow cloning and I was not
sure what to do. The issue is what must be provided for success in both
areas, and is there any code out there that will do the job as I do not want
to re-invent the wheel.
NB I looked into Boost but found it hard (impossible) to work out how to
correctly install on my WinXP m/c using Borland's C++ Builder 6.0 (or for
that matter BCC5.5). Even then I cannot be sure that the smart pointers
provided are suitable.
Regards
Jack Sharman