Table of Contents Previous Next
Logo
The C++ Utility Library : E.7 Handle Template
Copyright © 2003-2008 ZeroC, Inc.

E.7 Handle Template

IceUtil::Handle implements a smart reference-counted pointer type. Smart pointers are used to guarantee automatic deletion of heap-allocated class instances. (See Section 6.14.6 for a detailed explanation of smart pointers.)
Handle is a template class with the following interface:1
template<typename T>
class Handle : /* ... */ {
public:

    typedef T element_type;

    T* _ptr;

    T* operator>() const;
    T& operator*() const;
    T* get() const;

    operator bool() const;

    void swap(HandleBase& other);

    Handle(T* p = 0);

    template<typename Y>
    Handle(const Handle<Y>& r);

    Handle(const Handle& r);

    ~Handle();

    Handle& operator=(T* p);

    template<typename Y>
    Handle& operator=(const Handle<Y>& r);

    Handle& operator=(const Handle& r);

    template<class Y>
    static Handle dynamicCast(const HandleBase<Y>& r);

    template<class Y>
    static Handle dynamicCast(Y* p);
};

template<typename T, typename U>
bool operator==(const Handle<T>& lhs, const Handle<U>& rhs);

template<typename T, typename U>
bool operator!=(const Handle<T>& lhs, const Handle<U>& rhs);

template<typename T, typename U>
bool operator<(const Handle<T>& lhs, const Handle<U>& rhs);

template<typename T, typename U>
bool operator<=(const Handle<T>& lhs, const Handle<U>& rhs);

template<typename T, typename U>
bool operator>(const Handle<T>& lhs, const Handle<U>& rhs);

template<typename T, typename U>
bool operator>=(const Handle<T>& lhs, const Handle<U>& rhs);
The template argument must be a class that derives from Shared or SimpleShared (or that implements reference counting with the same interface as these classes); see page 1765 for a description of these classes.
This is quite a large interface, but all it really does is to faithfully mimic the behavior of ordinary C++ class instance pointers. Rather than discussing each member function in detail, we provide a simple overview here that outlines the most important points. Please see Section 6.14.6 for more examples of how to use smart pointers.
• element_type
This type definition follows the STL convention of defining the element type with the fixed name element_type so you can use it for template programming or the definition of generic containers.
• _ptr
This data member stores the pointer to the underlying heap-allocated class instance.
• Constructors, copy constructor, and assignment operators
These member functions allow you to construct, copy, and assign smart pointers as if they were ordinary pointers. In particular, the constructor and assignment operator are overloaded to work with raw C++ class instance pointers, which results in the "adoption" of the raw pointer by the smart pointer. For example, the following code works correctly and does not cause a memory leak:
typedef Handle<MyClass> MyClassPtr;

void foo(const MyClassPtr&);

// ...

foo(new MyClass); // OK, no leak here.
• operator->, operator*, and get
The arrow and indirection operators allow you to apply the usual pointer syntax to smart pointers to use the target of a smart pointer. The get member function returns the class instance pointer to the underlying reference-counted class instance; the return value is the value of _ptr.
• dynamicCast
This member function works exactly like a C++ dynamic_cast:2 it tests whether the argument supports the specified type and, if so, returns a non-null pointer; if the target does not support the specified type, it returns null. For example:
MyClassPtr p = ...;
MyOtherClassPtr o = ...;

o = MyOtherClassPtr::dynamicCast(p);
if (o)
{
    // o points at an instance of type MyOtherClass.
}
else
{
    // p points at something that is
    // not compatible with MyOtherClass.
}
Note that this example also illustrates the use of operator bool: when used in a boolean context, a smart pointer returns true if it is non-null and false otherwise.
• Comparison operators: ==, !=, <, <=, >, >=
The comparison operators compare the value of the underlying class instance pointer, that is, they compare the value returned by get. In other words, == returns true if two smart pointers point at the same underlying class instance, and the ordering operators compare the memory addresses of the underlying class instances.

1
Note that the actual implementation is split into a base and a derived class. For simplicity, we show the combined interface here. If you want to see the full implementation detail, it can be found in IceUtil/Handle.h.

2
The reason for not using an actual dynamic_cast and using a dynamicCast function instead is that dynamic_cast only operates on pointer types, but IceUtil::Handle is a class.

Table of Contents Previous Next
Logo