/*
    MultiNode sample code
    Henry Smith (henry@enigmasoftware.ca)

    A smart-pointer-like object for referring to MultiNodes
*/


#ifndef MultiNodeRef_H
#define MultiNodeRef_H

#include <cassert>

class MultiNodeImpl;

////////////////////////////////////////////////////////////////////////////////
//
//  MultiNodeRef
//  A smart-pointer-like object for referring to MultiNodes
//
////////////////////////////////////////////////////////////////////////////////

class MultiNodeRef
{
    public:
        MultiNodeRef (MultiNodeImpl* inPtr = 0) : mPtr(inPtr) {}
        MultiNodeRef (const MultiNodeRef& inRef) : mPtr(inRef.mPtr) {}
        ~MultiNodeRef () {}
       
        MultiNodeRef& operator = (const MultiNodeRef& rhs) {
            mPtr = rhs.mPtr;
            return (*this);
        }
       
        MultiNodeImpl& operator * () const {
            assert(mPtr != 0);
            return *mPtr;
        }

        MultiNodeImpl* operator -> () const {
            assert(mPtr != 0);
            return mPtr;
        }

        MultiNodeImpl* GetPtr () const {
            return mPtr;
        }

        friend bool operator == (const MultiNodeRef& lhs, const MultiNodeRef& rhs) { return lhs.mPtr == rhs.mPtr; }
        friend bool operator == (const MultiNodeImpl* lhs, const MultiNodeRef& rhs) { return lhs == rhs.mPtr; }
        friend bool operator == (const MultiNodeRef& lhs, const MultiNodeImpl* rhs) { return lhs.mPtr == rhs; }
        friend bool operator != (const MultiNodeRef& lhs, const MultiNodeRef& rhs) { return lhs.mPtr != rhs.mPtr; }
        friend bool operator != (const MultiNodeImpl* lhs, const MultiNodeRef& rhs) { return lhs != rhs.mPtr; }
        friend bool operator != (const MultiNodeRef& lhs, const MultiNodeImpl* rhs) { return lhs.mPtr != rhs; }

    private:
        MultiNodeImpl* mPtr;
};


////////////////////////////////////////////////////////////////////////////////
//
//  MultiNodeRefCast
//  A helper class providing casting facilities to a derived node type
//
////////////////////////////////////////////////////////////////////////////////

template <class T>
class MultiNodeRefCast
    : public MultiNodeRef
{
    typedef MultiNodeRef Super;

    public:
        MultiNodeRefCast (T* inPtr = 0) : Super(inPtr) {}
        MultiNodeRefCast (const MultiNodeRefCast& inRef) : Super(inRef) {}
        MultiNodeRefCast (const MultiNodeRef& inRef) : Super(inRef) {}
       
        T&  operator *  () const { return static_cast<T*>(Super::operator * ()); }
        T*  operator -> () const { return static_cast<T*>(Super::operator -> ()); }
        T*  GetPtr      () const { return static_cast<T*>(Super::GetPtr ()); }
};

////////////////////////////////////////////////////////////////////////////////
//
//  NullRef
//  The null MultiNodeRef value
//
////////////////////////////////////////////////////////////////////////////////

const MultiNodeRef NullRef;

#endif  // MultiNodeRef_H