f



Casting smart pointer?

I have a smart pointer class called Handle...

template <class T>
class Handle
{
public:
	Handle();
	Handle(T*);
	Handle(const Handle<T>&);
	~Handle();

        ...
private:
	T* m_pTarget;
};

that always points to a class derived from another class called
Handleable.  (Handleable contains the reference count)

Now if I have a class B and class D as follows:

class B : public Handleable {...}
class D : public B {...}

and then I have a function

    void f(Handle<B>)

and call it as follows:

    Handle<D> d;
    f(d);

I would like the compiler to automatically cast my handle from a
Handle<D> to a Handle<B> (as B is a base class of D).

Is this possible?

I thought of something like this:

template <class T>
class Handle
{
     ...
     template <class S>
         operator Handle<S>() { return Handle<S>( m_pTarget ); }
     ...
}

But this will be ambiguous with the copy constructor, correct?  Is
there a way to avoid this?

Thanks,
Andrew.

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Andrew
3/25/2009 12:34:16 PM
comp.lang.c++.moderated 10738 articles. 1 followers. allnor (8506) is leader. Post Follow

2 Replies
408 Views

Similar Articles

[PageSpeed] 17

Andrew Tomazos schrieb:
> I have a smart pointer class called Handle...
> 
> template <class T>
> class Handle
[...]
> Now if I have a class B and class D as follows:
> 
> class B : public Handleable {...}
> class D : public B {...}
> 
> and then I have a function
> 
>     void f(Handle<B>)
> 
> and call it as follows:
> 
>     Handle<D> d;
>     f(d);
> 
> I would like the compiler to automatically cast my handle from a
> Handle<D> to a Handle<B> (as B is a base class of D).

The usual way is to provide a templated constructor similar to the copy
constructor:

template<class Y>
Handle(Handle<Y> const& other);

If you also provide a copy constructor, then it will be preferred,
because it is more specialised than the templated constructor.

See also the implementation of boost::intrusive_ptr
or my linked_ptr ( http://draig.de/linked_ptr/ ).

-- 
Thomas

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Thomas
3/25/2009 7:46:13 PM
Andrew Tomazos schrieb:
> I have a smart pointer class called Handle...
> 
> template <class T>
> class Handle
> {
> public:
> 	Handle();
> 	Handle(T*);
> 	Handle(const Handle<T>&);
> 	~Handle();
> 
>         ...
> private:
> 	T* m_pTarget;
> };
> 
> that always points to a class derived from another class called
> Handleable.  (Handleable contains the reference count)

So why don't you make it a simple class that stores a pointer to
Handleable?

> I would like the compiler to automatically cast my handle from a
> Handle<D> to a Handle<B> (as B is a base class of D).
> 
> Is this possible?

Yes, quite easily if you have an method to retrieve the internal
pointer (let's call it get()).

template<class T>
class Handle
{
   /*...*/
public:
   T* get() const
   { return m_pTarget; }

   template<class U>
   Handle(Handle<U> const& other) : m_pTarget(other.get()) //(1)
   { /* do the ref-counting */ }
};

(1) compiles if and only if U* is convertible to T*, that is if U is
derived from T, T is void or U is T. The case T==void should be
a-voided by some sort of static assertion that Handle<void> can't be
instantiated, and the case U==T cannot arise because the compiler
would prefer the copy construtor over the templated one.

> 
> I thought of something like this:
> 
> template <class T>
> class Handle
> {
>      ...
>      template <class S>
>          operator Handle<S>() { return Handle<S>( m_pTarget ); }
>      ...
> }
> 
> But this will be ambiguous with the copy constructor, correct?  Is
> there a way to avoid this?

Prefer conversion by some constructor of the target type over
conversion by some conversion operator.

There are several libraries that provide means to detect at compile
time whether one type is derived from another, e.g. the loki library
and I am pretty sure you'll find something useful in the boost
libraries as well.

greets
Arne

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Arne
3/25/2009 7:47:23 PM
Reply: