Smart pointer template question

G

Gonçalo Rodrigues

Hi all,

(note: newbie alert)

Suppose you have a hierarchy of objects that you deal with via smart
pointers, e.g. something like:

template<typename T>
class Ref {
private:
T* ptr;
<etc..>
};

Now suppose also that the hierarchy is singly-rooted and call the root
class Object. Most of the times a smart pointer to Object is all that
you will ever need, but there are times when you need have a smart
pointer to a derived class, so what is the best way to write the Ref
template so that it reflects the single-rootedness of the hierarchy?

My best up to now is

class Ref {
private:
Object* ptr;
<etc...>
};

template<typename T>
class PRef : public Ref {
private:
T* ptr;
<etc...>
};

But this is far from optimal. Any ideas?

TIA, with my best regards,
G. Rodrigues
 
V

Victor Bazarov

Gonçalo Rodrigues said:
(note: newbie alert)

Suppose you have a hierarchy of objects that you deal with via smart
pointers, e.g. something like:

template<typename T>
class Ref {
private:
T* ptr;
<etc..>
};

Now suppose also that the hierarchy is singly-rooted and call the root
class Object. Most of the times a smart pointer to Object is all that
you will ever need, but there are times when you need have a smart
pointer to a derived class, so what is the best way to write the Ref
template so that it reflects the single-rootedness of the hierarchy?

My best up to now is

class Ref {
private:
Object* ptr;
<etc...>
};

template<typename T>
class PRef : public Ref {
private:
T* ptr;
<etc...>
};

But this is far from optimal. Any ideas?

Why not let the Ref to be derived from Object too? Something like

template<typename T> class Ref : public Object {
};

Now, it's definitely single-rooted.

V
 
G

Gonçalo Rodrigues

Why not let the Ref to be derived from Object too? Something like

template<typename T> class Ref : public Object {
};

Now, it's definitely single-rooted.

V

For one thing the Object-rooted hierarchy and the mirror hierarchy of
smart pointers are conceptually distinct things. The Object hierarchy
is the *real thing*, the Ref hierarchy is just a *handle* on the real
thing, or, in a more platonic mood, a shadow in the wall of a cave of
the real thing. In particular, a Ref would inherit Object's
functionality/interface which doesn't make sense.

But more importantly, suppose there is a subclass of Object that
contain *Ref's* to other Object's (this is another rule I forgot to
state: any composite objects contain Ref's or smart pointers to
Object's *not* pointers). Take, for example a Tuple of Object's. A
possible definition/implementation would be

class Tuple : public Object {
private:
Ref* array;
<etc...>
}

In this way I can put any Object in a Tuple and polymorphically elbow
my way from there due to the singly-rooted hierarchy. I don't see how
I can achieve this with your solution.

TIA, best regards,
G. Rodrigues
 
H

Howard Hinnant

Gon?alo Rodrigues said:
Hi all,

(note: newbie alert)

Suppose you have a hierarchy of objects that you deal with via smart
pointers, e.g. something like:

template<typename T>
class Ref {
private:
T* ptr;
<etc..>
};

Now suppose also that the hierarchy is singly-rooted and call the root
class Object. Most of the times a smart pointer to Object is all that
you will ever need, but there are times when you need have a smart
pointer to a derived class, so what is the best way to write the Ref
template so that it reflects the single-rootedness of the hierarchy?

My best up to now is

class Ref {
private:
Object* ptr;
<etc...>
};

template<typename T>
class PRef : public Ref {
private:
T* ptr;
<etc...>
};

But this is far from optimal. Any ideas?

You might want to mimic the design of boost::shared_ptr (
http://www.boost.org/libs/smart_ptr/shared_ptr.htm ) in this respect:

template<class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r);

template<class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r);

template<class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);

-Howard
 
M

Michiel Salters

Gonçalo Rodrigues said:
Hi all,

(note: newbie alert)

Suppose you have a hierarchy of objects that you deal with via smart
pointers, e.g. something like:

template<typename T>
class Ref {
private:
T* ptr;
<etc..>
};

Now suppose also that the hierarchy is singly-rooted and call the root
class Object. Most of the times a smart pointer to Object is all that
you will ever need, but there are times when you need have a smart
pointer to a derived class, so what is the best way to write the Ref
template so that it reflects the single-rootedness of the hierarchy?

My best up to now is

class Ref {
private:
Object* ptr;
<etc...>
};

template<typename T>
class PRef : public Ref {
private:
T* ptr;
<etc...>
};

But this is far from optimal. Any ideas?

Yes. For starters, note that DerivedObject* does NOT inherit from
Object*, even if DerivedObject inherits from Object. So dumb pointers
don't follow this pattern. They probably do share an implementation,
so the better approach might be:

template <typename T>
class PRef { // [sic]
private: Ref ptr;
public: T& operator*() const { return *ptr; }
}

Regards,
Michiel Salters
 
G

Gonçalo Rodrigues

Yes. For starters, note that DerivedObject* does NOT inherit from
Object*, even if DerivedObject inherits from Object.

Yeah, this is the real problem: mirroring the original class hierarchy
in the Ref hierarchy so that if U is a T then Ref<U> is a Ref<T>. In
particular every Ref<T> is a Ref<Object> (for T an Object of course).

Up to now, if you exclude a brief bout with Java, my programming
experience has been with dynamically typed languages where this
mirroring problem is easy because classes are themselves first-class
citizens. So I'm still getting the hang of C++ and the
statically-typed framework and all the inherent complexities of
templates and the like.
So dumb pointers
don't follow this pattern. They probably do share an implementation,
so the better approach might be:

template <typename T>
class PRef { // [sic]
private: Ref ptr;
public: T& operator*() const { return *ptr; }
}

Regards,
Michiel Salters

Thanks. Together with Mr. Hinnant suggestion this might actually get
me somewhere.

With my best regards,
G. Rodrigues.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top