473,396 Members | 1,846 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Objects containing a smart ptr (pimpl) and stored in STL containers - help please

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
Jul 22 '05 #1
3 2179
On Thu, 12 Aug 2004 09:15:12 -0700, JackC wrote:
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
This reason is not valid because you can have the destructor of your
class generated at a point where Impl is complete. The trick is to
declare the destructor of T in the header file (even if it's empty)
and define it (even if it's empty) in the implementation file.

In fact, you seem to be doing it above. I don't think there is a
problem with that.
(b) auto_ptr does not provide the correct copy behaviour for
STL containers.
This is a better reason, but not completely correct because you are
not storing any auto_ptr in any container.

The problem is with T because of not having the copy constructor and
the assignment operator that do the right thing. T is the class that
relies on auto_ptr in its implementation and it must be the class to
ensure T's suitability to containers.
is there any code out there
that will do the job as I do not want to re-invent the wheel.
Then use boost::shared_ptr.
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.


The installation is as simple as copying the header files to a
directory and adding that directory to the header file search path. (I
am not sure but I think the header files don't need any make
process.)

Here is a solution using auto_ptr:

#include <memory>

class T
{
public:

T();
T(T const &);
T & operator= (T const &);
~T();

void swap(T & other);

private:
typedef struct Impl;
std::auto_ptr<Impl> pimpl;
};

struct T::Impl
{
Impl() {}
Impl(Impl const &) {}
Impl & operator= (Impl const &);
~Impl() {}
};

T::T()
:
pimpl (new Impl())
{}

T::T(T const & other)
:
pimpl(new Impl(*(other.pimpl)))
{}

void T::swap(T & other)
{
std::swap(pimpl, other.pimpl);
}

T & T::operator= (T const & other)
{
T temp(other);
this->swap(temp);
return *this;
}

// There is NO PROBLEM here, because Impl is completely defined when
// auto_ptr::~auto_ptr is used
T::~T()
{}

#include <vector>

int main()
{
std::vector<T> Ts;
Ts.push_back(T());
Ts.push_back(T());
}

Ali
Jul 22 '05 #2
In message <cf*******************@news.demon.co.uk>, JackC
<ja**@clearcutsoftware.com> writes
[classic pimpl problem]

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).
You don't need to "install" at all unless you need to use the parts of
Boost that require external libraries to be built - and its smart
pointers don't. Just extract the file hierarchy from the
zip/tar/whatever and add the root (e.g. boost_1_29_0) to the list of
include directories in your project. (You may find that versions later
than 1.29 don't work properly with BCC5.5 or earlier, which is why I use
that as an example ;-) .

Even then I cannot be sure that the smart pointers
provided are suitable.


boost::shared_ptr does exactly what its name suggests, and objects
containing them can be stored in STL containers without problems.

It also contains trickery to deal correctly with attempts to delete
incomplete types.

Whether you want your objects to be freely copyable with shared
ownership problems, only you can decide.

--
Richard Herring
Jul 22 '05 #3
"JackC" <ja**@clearcutsoftware.com> wrote in message news:<cf*******************@news.demon.co.uk>...
Hi

Problem:
I wish to use a pimpl to hide implementation/storage of a class (T), but I .... 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.
Try not removing the copy and assignment operators!!
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.
As you are not deriving from T::Impl then you don't need to do
anything, the default behaviour is what you want.
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).
For most of Boost you just expand the archive and add it to the
include path. (There are a few libraries within you may need to
build, but not the smart pointers.)
Even then I cannot be sure that the smart pointers
provided are suitable.


boost::shared_ptr provides shared ownership semantics - so, unless you
want copies of T to share implementation, you must provide the copy
semantics for yourself.
--
Alan Griffiths
http://www.octopull.demon.co.uk/
Jul 22 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Asfand Yar Qazi | last post by:
Hello. Partly for learning purposes, I have written a smart pointer class. Could you please tell me what's wrong with it? (I know there's something wrong with it, but just not what!) Note...
22
by: Claudio Jolowicz | last post by:
Is it possible to store unique objects in an STL container? Suppose an object of class C is unique: class C { public: C() {} ~C() {} private:
9
by: christopher diggins | last post by:
I would like to survey how widespread the usage of smart pointers in C++ code is today. Any anecdotal experience about the frequency of usage of smart pointer for dynamic allocation in your own...
7
by: Jo | last post by:
Hi, How can i differentiate between static and dynamic allocated objects? For example: void SomeFunction1() { CObject *objectp = new CObject; CObject object;
21
by: George Exarchakos | last post by:
Hi everyone, I'd like your help... Can we have a std::list<BASEwhere BASE be the base class of a class hierarchy? I want to add to this list objects that are inherited from BASE class but not...
13
by: r.z. | last post by:
I logged construtor and destructor calls for one of my classes and I discovered that the constructor was called only once while the destructor was called 3 times for a single object. I have a...
15
by: Juha Nieminen | last post by:
I'm sure this is not a new idea, but I have never heard about it before. I'm wondering if this could work: Assume that you have a common base class and a bunch of classes derived from it, and...
5
by: Jim | last post by:
Hi, Just wondering which is better vector<record *r; r.push_back(new record(x,y)); or vector<recordr; r.push_back(record(x,y));
3
by: Adrian | last post by:
In the following code example I am trying to create a generic interface for a bunch of objects. Each concrete type is stored in its own container and the a container of pointer's to base is used so I...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.