// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_TEMPLATE_H
#define OB_TEMPLATE_H

// ----------------------------------------------------------------------
// T_var templates
// ----------------------------------------------------------------------

//
// T_var template for fixed-length general data types
//
template<class T>
class OBFixVar
{
    T* ptr_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    OBFixVar() : ptr_(0) { }
    OBFixVar(T* p) : ptr_(p) { assert_nca(p, OBNCANullInit); }
#ifdef HAVE_VCPLUSPLUS_BUGS
    OBFixVar(const OBFixVar<T>& r)
    { ptr_ = r.ptr_ ? new T(*r.ptr_) : 0 ; }
#else
    OBFixVar(const OBFixVar<T>& r)
	: ptr_(r.ptr_ ? new T(*r.ptr_) : 0) { }
#endif
    ~OBFixVar() { delete ptr_; }

    OBFixVar<T>& operator=(T*);
    OBFixVar<T>& operator=(const OBFixVar<T>&);

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    T* operator->() const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_; }
#else
    T* operator->()
    { assert_nca(ptr_, OBNCANullPtr); return ptr_; }
    const T* operator->() const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_; }
#endif

    const T& in() const { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
    T& inout() { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
    T& out() { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
    const T& _retn() { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    operator T&() const
    { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
#else
#ifndef OB_ONLY_IN_TYPE_CONVERSION
    operator T&()
    { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
#endif
    operator const T&() const
    { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
#endif
};

//
// T_var template for variable-length general data types
//
template<class T>
class OBVarVar
{
    T* ptr_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    OBVarVar() : ptr_(0) { }
    OBVarVar(T* p) : ptr_(p) { assert_nca(p, OBNCANullInit); }
#ifdef HAVE_VCPLUSPLUS_BUGS
    OBVarVar(const OBVarVar<T>& r)
    { ptr_ = r.ptr_ ? new T(*r.ptr_) : 0 ; }
#else
    OBVarVar(const OBVarVar<T>& r)
	: ptr_(r.ptr_ ? new T(*r.ptr_) : 0) { }
#endif
    ~OBVarVar() { delete ptr_; }

    OBVarVar<T>& operator=(T*);
    OBVarVar<T>& operator=(const OBVarVar<T>&);

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    T* operator->() const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_; }
#else
    T* operator->()
    { assert_nca(ptr_, OBNCANullPtr); return ptr_; }
    const T* operator->() const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_; }
#endif

    const T& in() const { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
    T& inout() { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
    T*& out() { delete ptr_; ptr_ = 0; return ptr_; }
    T* _retn() { T* ret = ptr_; ptr_ = 0; return ret; }

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    operator T&() const
    { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
#else
#ifndef OB_ONLY_IN_TYPE_CONVERSION
    operator T&()
    { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
#endif
    operator const T&() const
    { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
#endif
    operator T*&() { return ptr_; }
};

//
// T_var template for sequence types
//
template<class T>
class OBSeqVar
{
    T* ptr_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    OBSeqVar()
	: ptr_(0) { }
    OBSeqVar(T* p) : ptr_(p) { assert_nca(p, OBNCANullInit); }
#ifdef HAVE_VCPLUSPLUS_BUGS
    OBSeqVar(const OBSeqVar<T>& r)
    { ptr_ = r.ptr_ ? new T(*r.ptr_) : 0 ; }
#else
    OBSeqVar(const OBSeqVar<T>& r)
	: ptr_(r.ptr_ ? new T(*r.ptr_) : 0) { }
#endif
    ~OBSeqVar() { delete ptr_; }

    OBSeqVar<T>& operator=(T*);
    OBSeqVar<T>& operator=(const OBSeqVar<T>&);

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    T* operator->() const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_; }
#else
    T* operator->()
    { assert_nca(ptr_, OBNCANullPtr); return ptr_; }
    const T* operator->() const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_; }
#endif

#ifdef HAVE_NO_TYPENAME
    typedef T::SubType SubType;
    typedef T::ConstSubType ConstSubType;
#else
    typedef typename T::SubType SubType;
    typedef typename T::ConstSubType ConstSubType;
#endif

    const T& in() const { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
    T& inout() { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
    T*& out() { delete ptr_; ptr_ = 0; return ptr_; }
    T* _retn() { T* ret = ptr_; ptr_ = 0; return ret; }

    SubType operator[](short idx)
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
    SubType operator[](unsigned short idx)
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
#ifdef HAVE_VCPLUSPLUS_BUGS
    ConstSubType operator[](short idx) const
    { assert_nca(ptr_, OBNCANullPtr);
      return (ConstSubType)(ptr_ -> operator[](idx)); }
    ConstSubType operator[](unsigned short idx) const
    { assert_nca(ptr_, OBNCANullPtr);
      return (ConstSubType)(ptr_ -> operator[](idx)); }
#else
    ConstSubType operator[](short idx) const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
    ConstSubType operator[](unsigned short idx) const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
#endif

    SubType operator[](int idx)
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
    SubType operator[](unsigned int idx)
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
#ifdef HAVE_VCPLUSPLUS_BUGS
    ConstSubType operator[](int idx) const
    { assert_nca(ptr_, OBNCANullPtr);
      return (ConstSubType)(ptr_ -> operator[](idx)); }
    ConstSubType operator[](unsigned int idx) const
    { assert_nca(ptr_, OBNCANullPtr);
      return (ConstSubType)(ptr_ -> operator[](idx)); }
#else
    ConstSubType operator[](int idx) const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
    ConstSubType operator[](unsigned int idx) const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
#endif

    SubType operator[](long idx)
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
    SubType operator[](unsigned long idx)
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
#ifdef HAVE_VCPLUSPLUS_BUGS
    ConstSubType operator[](long idx) const
    { assert_nca(ptr_, OBNCANullPtr);
      return (ConstSubType)(ptr_ -> operator[](idx)); }
    ConstSubType operator[](unsigned long idx) const
    { assert_nca(ptr_, OBNCANullPtr);
      return (ConstSubType)(ptr_ -> operator[](idx)); }
#else
    ConstSubType operator[](long idx) const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
    ConstSubType operator[](unsigned long idx) const
    { assert_nca(ptr_, OBNCANullPtr); return ptr_ -> operator[](idx); }
#endif

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    operator T&() const
    { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
#else
#ifndef OB_ONLY_IN_TYPE_CONVERSION
    operator T&()
    { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
#endif
    operator const T&() const
    { assert_nca(ptr_, OBNCANullDeref); return *ptr_; }
#endif
    operator T*&() { return ptr_; }
};

//
// T_var template for fixed-length array types
//
template<class T_slice, class T, CORBA_ULong n>
class OBFixArrayVar
{
    T_slice* ptr_;

public:

    OBFixArrayVar() : ptr_(0) { }
    OBFixArrayVar(T_slice* p) : ptr_(p) { assert_nca(p, OBNCANullInit); }
    OBFixArrayVar(const OBFixArrayVar<T_slice, T, n>&);
    ~OBFixArrayVar() { delete [] (T*) ptr_; }
    
    OBFixArrayVar<T_slice, T, n>& operator=(T_slice*);
    OBFixArrayVar<T_slice, T, n>&
    operator=(const OBFixArrayVar<T_slice, T, n>&);

#ifdef HAVE_VCPLUSPLUS_BUGS
    const T_slice* in() const { return (const T_slice*)ptr_; }
#else
    const T_slice* in() const { return ptr_; }
#endif
    T_slice* inout() { return ptr_; }
    T_slice* out() { delete [] (T*) ptr_; ptr_ = 0; return ptr_; }
    T_slice* _retn() { T_slice* ret = ptr_; ptr_ = 0; return ret; }

    T_slice& operator[](short idx) { return ptr_[idx]; }
    const T_slice& operator[](short idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned short idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned short idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](int idx) { return ptr_[idx]; }
    const T_slice& operator[](int idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned int idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned int idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](long idx) { return ptr_[idx]; }
    const T_slice& operator[](long idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned long idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned long idx) const
    { return ((const T_slice*)ptr_)[idx]; }

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    operator T_slice*() const { return ptr_; }
#else
#ifndef OB_ONLY_IN_TYPE_CONVERSION
    operator T_slice*() { return ptr_; }
#endif
#ifdef HAVE_VCPLUSPLUS_BUGS
    operator const T_slice*() const { return (const T_slice*)ptr_; }
#else
    operator const T_slice*() const { return ptr_; }
#endif
#endif

};
    
//
// T_var template for variable-length array types
//
template<class T_slice, class T, CORBA_ULong n>
class OBVarArrayVar
{
    T_slice* ptr_;

public:

    OBVarArrayVar() : ptr_(0) { }
    OBVarArrayVar(T_slice* p) : ptr_(p) { assert_nca(p, OBNCANullInit); }
    OBVarArrayVar(const OBVarArrayVar<T_slice, T, n>&);
    ~OBVarArrayVar() { delete [] (T*) ptr_; }
    
    OBVarArrayVar<T_slice, T, n>& operator=(T_slice*);
    OBVarArrayVar<T_slice, T, n>&
    operator=(const OBVarArrayVar<T_slice, T, n>&);

#ifdef HAVE_VCPLUSPLUS_BUGS
    const T_slice* in() const { return (const T_slice*)ptr_; }
#else
    const T_slice* in() const { return ptr_; }
#endif
    T_slice* inout() { return ptr_; }
    T_slice*& out() { delete [] (T*) ptr_; ptr_ = 0; return ptr_; }
    T_slice* _retn() { T_slice* ret = ptr_; ptr_ = 0; return ret; }

    T_slice& operator[](short idx) { return ptr_[idx]; }
    const T_slice& operator[](short idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned short idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned short idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](int idx) { return ptr_[idx]; }
    const T_slice& operator[](int idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned int idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned int idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](long idx) { return ptr_[idx]; }
    const T_slice& operator[](long idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned long idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned long idx) const
    { return ((const T_slice*)ptr_)[idx]; }

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    operator T_slice*&() const { return (T_slice*&)ptr_; }
#else
#ifndef OB_ONLY_IN_TYPE_CONVERSION
    operator T_slice*&() { return ptr_; }
#endif
#ifdef HAVE_VCPLUSPLUS_BUGS
    operator const T_slice*() const { return (const T_slice*)ptr_; }
#else
    operator const T_slice*() const { return ptr_; }
#endif
#endif
};
    
//
// Template for fixed-length array forany types
//
template<class T_slice, class T, CORBA_ULong n>
class OBFixArrayForAny
{
    T_slice* ptr_;
    CORBA_Boolean nocopy_;

public:

    OBFixArrayForAny() : ptr_(0), nocopy_(false) { }
    OBFixArrayForAny(T_slice* p, CORBA_Boolean nc = false)
	: ptr_(p), nocopy_(nc) { };
    OBFixArrayForAny(const OBFixArrayForAny<T_slice, T, n>& r,
		  CORBA_Boolean nc = false)
	: ptr_(r.ptr_), nocopy_(nc) { };

    CORBA_Boolean nocopy() const { return nocopy_; }

    OBFixArrayForAny<T_slice, T, n>& operator=(T_slice* p)
    { ptr_ = p; return *this; }
    OBFixArrayForAny<T_slice, T, n>&
    operator=(const OBFixArrayForAny<T_slice, T, n>& r)
    { ptr_ = r.ptr_; return *this; }

#ifdef HAVE_VCPLUSPLUS_BUGS
    const T_slice* in() const { return (const T_slice*)ptr_; }
#else
    const T_slice* in() const { return ptr_; }
#endif
    T_slice* inout() { return ptr_; }
    T_slice* out() { delete [] (T*) ptr_; ptr_ = 0; return ptr_; }
    T_slice* _retn() { T_slice* ret = ptr_; ptr_ = 0; return ret; }

    T_slice& operator[](short idx) { return ptr_[idx]; }
    const T_slice& operator[](short idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned short idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned short idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](int idx) { return ptr_[idx]; }
    const T_slice& operator[](int idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned int idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned int idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](long idx) { return ptr_[idx]; }
    const T_slice& operator[](long idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned long idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned long idx) const
    { return ((const T_slice*)ptr_)[idx]; }

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    operator T_slice*() const { return ptr_; }
#else
#ifndef OB_ONLY_IN_TYPE_CONVERSION
    operator T_slice*() { return ptr_; }
#endif
#ifdef HAVE_VCPLUSPLUS_BUGS
    operator const T_slice*() const { return (const T_slice*)ptr_; }
#else
    operator const T_slice*() const { return ptr_; }
#endif
#endif
};
    
//
// Template for variable-length array forany types
//
template<class T_slice, class T, CORBA_ULong n>
class OBVarArrayForAny
{
    T_slice* ptr_;
    CORBA_Boolean nocopy_;

public:

    OBVarArrayForAny() : ptr_(0), nocopy_(false) { }
    OBVarArrayForAny(T_slice* p, CORBA_Boolean nc = false)
	: ptr_(p), nocopy_(nc) { };
    OBVarArrayForAny(const OBVarArrayForAny<T_slice, T, n>& r,
		  CORBA_Boolean nc = false)
	: ptr_(r.ptr_), nocopy_(nc) { };

    CORBA_Boolean nocopy() const { return nocopy_; }

    OBVarArrayForAny<T_slice, T, n>& operator=(T_slice* p)
    { ptr_ = p; return *this; }
    OBVarArrayForAny<T_slice, T, n>&
    operator=(const OBVarArrayForAny<T_slice, T, n>& r)
    { ptr_ = r.ptr_; return *this; }

#ifdef HAVE_VCPLUSPLUS_BUGS
    const T_slice* in() const { return (const T_slice*)ptr_; }
#else
    const T_slice* in() const { return ptr_; }
#endif
    T_slice* inout() { return ptr_; }
    T_slice*& out() { delete [] (T*) ptr_; ptr_ = 0; return ptr_; }
    T_slice* _retn() { T_slice* ret = ptr_; ptr_ = 0; return ret; }

    T_slice& operator[](short idx) { return ptr_[idx]; }
    const T_slice& operator[](short idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned short idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned short idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](int idx) { return ptr_[idx]; }
    const T_slice& operator[](int idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned int idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned int idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](long idx) { return ptr_[idx]; }
    const T_slice& operator[](long idx) const
    { return ((const T_slice*)ptr_)[idx]; }
    T_slice& operator[](unsigned long idx) { return ptr_[idx]; }
    const T_slice& operator[](unsigned long idx) const
    { return ((const T_slice*)ptr_)[idx]; }

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    operator T_slice*&() const { return (T_slice*&)ptr_; }
#else
#ifndef OB_ONLY_IN_TYPE_CONVERSION
    operator T_slice*&() { return ptr_; }
#endif
#ifdef HAVE_VCPLUSPLUS_BUGS
    operator const T_slice*() const { return (const T_slice*)ptr_; }
#else
    operator const T_slice*() const { return ptr_; }
#endif
#endif
};
    
//
// Template for object reference _var types
//
class OBObjBase
{
};

template<class T> class OBObjForSeq;

template<class T>
class OBObjVar : public OBObjBase
{
    //
    // Make sure that widening between object reference _var types
    // require a call to _duplicate()
    //
    OBObjVar(const OBObjBase&) { }
    void operator=(const OBObjBase&) { }

    T* ptr_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    OBObjVar() : ptr_(0) { }
    OBObjVar(T* p) : ptr_(p) { }
    OBObjVar(const OBObjVar<T>& r) : ptr_(r.ptr_) { OBDuplicate(ptr_); }
    OBObjVar(const OBObjForSeq<T>&);
    ~OBObjVar() { OBRelease(ptr_); }

    OBObjVar<T>& operator=(T* p)
    {
	OBRelease(ptr_);
	ptr_ = p;
	return *this;
    }
    OBObjVar<T>& operator=(const OBObjVar<T>& r)
    {
	if(r.ptr_ != ptr_)
	{
	    OBRelease(ptr_);
	    ptr_ = r.ptr_;
	    OBDuplicate(ptr_);
	}
	return *this;
    }
    OBObjVar<T>& operator=(const OBObjForSeq<T>&);

    T* operator->() const { assert_nca(ptr_, OBNCANullPtr); return ptr_; }

    T* in() const { return ptr_; }
    T*& inout() { return ptr_; }
    T*& out() { OBRelease(ptr_); ptr_ = 0; return ptr_; }
    T* _retn() { T* ret = ptr_; ptr_ = 0; return ret; }

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    operator T*&() const { return (T*&)ptr_; }
#else
#ifndef OB_ONLY_IN_TYPE_CONVERSION
    operator T*&() { return ptr_; }
#endif
    operator T*() const { return ptr_; }
#endif
};

//
// Object reference type used by object reference sequences
//
template<class T>
class OBObjForSeq : public OBObjBase
{	
    //
    // Make sure that widening between object reference _var types
    // require a call to _duplicate()
    //
    void operator=(const OBObjBase&) { }
    OBObjForSeq(const OBObjBase&) { }

    T** ptr_;
    CORBA_Boolean rel_;
    
public:
    
    //
    // ORBacus specific constructor that works together with
    // the corresponding sequence type
    //
    OBObjForSeq(T** p, CORBA_Boolean rel) : ptr_(p), rel_(rel) { }
    OBObjForSeq(const OBObjForSeq<T>& r) : ptr_(r.ptr_), rel_(r.rel_) { }

    //
    // Standard IDL to C++ Mapping
    //
    OBObjForSeq<T>& operator=(T* p)
    {
	if(rel_)
	    OBRelease(*ptr_);
	*ptr_ = p;
	return *this;
    }
    OBObjForSeq<T>& operator=(const OBObjVar<T>& r)
    {
	if(r.in() != *ptr_)
	{
	    if(rel_)
		OBRelease(*ptr_);
	    *ptr_ = r.in();
	    OBDuplicate(*ptr_);
	}
	return *this;
    }
    OBObjForSeq<T>& operator=(const OBObjForSeq<T>& r)
    {
	if(*r.ptr_ != *ptr_)
	{
	    if(rel_)
		OBRelease(*ptr_);
	    *ptr_ = *r.ptr_;
	    OBDuplicate(*ptr_);
	}
	return *this;
    }

    T* operator->() const { assert_nca(*ptr_, OBNCANullPtr); return *ptr_; }

    T* in() const { return *ptr_; }
    T*& inout() { return *ptr_; }
    T*& out()
    {
	if(rel_)
	    OBRelease(*ptr_);
	*ptr_ = 0;
	return *ptr_;
    }
    T* _retn() { T* ret = *ptr_; *ptr_ = 0; return ret; }

#ifdef HAVE_NO_CONST_TYPE_CONVERSION_OVERLOAD
    operator T*&() const { return (T*&)(*ptr_); }
#else
#ifndef OB_ONLY_IN_TYPE_CONVERSION
    operator T*&() { return *ptr_; }
#endif
    operator T*() const { return *ptr_; }
#endif
};

template<class T>
inline
OBObjVar<T>::OBObjVar(const OBObjForSeq<T>& r)
    : ptr_(r.in())
{
    OBDuplicate(ptr_);
}

template<class T>
inline OBObjVar<T>&
OBObjVar<T>::operator=(const OBObjForSeq<T>& r)
{
    if(r.in() != ptr_)
    {
	OBRelease(ptr_);
	ptr_ = r.in();
	OBDuplicate(ptr_);
    }
    return *this;
}

// ----------------------------------------------------------------------
// Sequences
// ----------------------------------------------------------------------

//
// Template for fixed-length general unbounded sequence type
//
template<class T>
class OBFixSeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_ULong off_;
    CORBA_Boolean rel_;
    T* data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T* allocbuf(CORBA_ULong n) { return new T[n]; }
    static void freebuf(T* p) { delete [] p; }

    OBFixSeq();
    OBFixSeq(CORBA_ULong);
    OBFixSeq(CORBA_ULong, CORBA_ULong, T*, CORBA_Boolean = false);
    OBFixSeq(const OBFixSeq<T>&);
    ~OBFixSeq() { if(rel_) freebuf(data_); }

    OBFixSeq<T>& operator=(const OBFixSeq<T>&);

    CORBA_ULong maximum() const { return max_; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef T& SubType;
    typedef const T& ConstSubType;

    T& operator[](CORBA_ULong idx)
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx + off_]; }
    const T& operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx + off_]; }

    //
    // Additional ORBacus specific functions
    //
    T* data() { return data_ + off_; }
    const T* data() const { return data_ + off_; }

    void insert(const T&);
    void append(const T&);
    void remove(CORBA_ULong);

    void consume(OBFixSeq<T>&);
};

//
// Template for fixed-length general bounded sequence type
//
template<class T, CORBA_ULong max>
class OBBndFixSeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_Boolean rel_;
    T* data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T* allocbuf(CORBA_ULong n) { return new T[n]; }
    static void freebuf(T* p) { delete [] p; }

    OBBndFixSeq();
    OBBndFixSeq(CORBA_ULong, T*, CORBA_Boolean = false);
    OBBndFixSeq(const OBBndFixSeq<T, max>&);
    ~OBBndFixSeq() { if(rel_) freebuf(data_); }

    OBBndFixSeq<T, max>& operator=(const OBBndFixSeq<T, max>&);

    CORBA_ULong maximum() const { return max; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef T& SubType;
    typedef const T& ConstSubType;

    T& operator[](CORBA_ULong idx)
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
    const T& operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }

    //
    // Additional ORBacus specific functions
    //
    T* data() { return data_; }
    const T* data() const { return data_; }

    void consume(OBBndFixSeq<T, max>&);
};

//
// Template for variable-length general unbounded sequence type
//
template<class T>
class OBVarSeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_ULong off_;
    CORBA_Boolean rel_;
    T* data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T* allocbuf(CORBA_ULong n) { return new T[n]; }
    static void freebuf(T* p) { delete [] p; }

    OBVarSeq();
    OBVarSeq(CORBA_ULong);
    OBVarSeq(CORBA_ULong, CORBA_ULong, T*, CORBA_Boolean = false);
    OBVarSeq(const OBVarSeq<T>&);
    ~OBVarSeq() { if(rel_) freebuf(data_); }

    OBVarSeq<T>& operator=(const OBVarSeq<T>&);

    CORBA_ULong maximum() const { return max_; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef T& SubType;
    typedef const T& ConstSubType;

    T& operator[](CORBA_ULong idx)
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx + off_]; }
    const T& operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx + off_]; }

    //
    // Additional ORBacus specific functions
    //
    T* data() { return data_ + off_; }
    const T* data() const { return data_ + off_; }

    void insert(const T&);
    void append(const T&);
    void remove(CORBA_ULong);

    void consume(OBVarSeq<T>&);
};

//
// Template for variable-length general bounded sequence type
//
template<class T, CORBA_ULong max>
class OBBndVarSeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_Boolean rel_;
    T* data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T* allocbuf(CORBA_ULong n) { return new T[n]; }
    static void freebuf(T* p) { delete [] p; }

    OBBndVarSeq();
    OBBndVarSeq(CORBA_ULong, T*, CORBA_Boolean = false);
    OBBndVarSeq(const OBBndVarSeq<T, max>&);
    ~OBBndVarSeq() { if(rel_) freebuf(data_); }

    OBBndVarSeq<T, max>& operator=(const OBBndVarSeq<T, max>&);

    CORBA_ULong maximum() const { return max; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef T& SubType;
    typedef const T& ConstSubType;

    T& operator[](CORBA_ULong idx)
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
    const T& operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }

    //
    // Additional ORBacus specific functions
    //
    T* data() { return data_; }
    const T* data() const { return data_; }

    void consume(OBBndVarSeq<T, max>&);
};

//
// Template for fixed-length array unbounded sequence type
//
template<class T_slice, class T, CORBA_ULong n>
class OBFixArraySeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_Boolean rel_;
    T_slice** data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T_slice** allocbuf(CORBA_ULong);
    static void freebuf(T_slice**);

    OBFixArraySeq();
    OBFixArraySeq(CORBA_ULong);
    OBFixArraySeq(CORBA_ULong, CORBA_ULong, T_slice**, CORBA_Boolean = false);
    OBFixArraySeq(const OBFixArraySeq<T_slice, T, n>&);
    ~OBFixArraySeq() { if(rel_) freebuf(data_); }

    OBFixArraySeq<T_slice, T, n>&
    operator=(const OBFixArraySeq<T_slice, T, n>&);

    CORBA_ULong maximum() const { return max_; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef T_slice*& SubType;
    typedef const T_slice* ConstSubType;

    T_slice*& operator[](CORBA_ULong idx)
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
#ifdef HAVE_VCPLUSPLUS_BUGS
    const T_slice* operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange);
      return (const T_slice*)data_[idx]; }
#else
    const T_slice* operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
#endif

    //
    // Additional ORBacus specific functions
    //
    T_slice** data() { return data_; }
    T_slice* const * data() const { return data_; }

    void consume(OBFixArraySeq<T_slice, T, n>&);
};

//
// Template for fixed-length array bounded sequence type
//
template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
class OBBndFixArraySeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_Boolean rel_;
    T_slice** data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T_slice** allocbuf(CORBA_ULong);
    static void freebuf(T_slice**);

    OBBndFixArraySeq();
    OBBndFixArraySeq(CORBA_ULong, T_slice**, CORBA_Boolean = false);
    OBBndFixArraySeq(const OBBndFixArraySeq<T_slice, T, n, max>&);
    ~OBBndFixArraySeq() { if(rel_) freebuf(data_); }

    OBBndFixArraySeq<T_slice, T, n, max>&
    operator=(const OBBndFixArraySeq<T_slice, T, n, max>&);

    CORBA_ULong maximum() const { return max; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef T_slice*& SubType;
    typedef const T_slice* ConstSubType;

    T_slice*& operator[](CORBA_ULong idx)
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
#ifdef HAVE_VCPLUSPLUS_BUGS
    const T_slice* operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange);
      return (const T_slice*)data_[idx]; }
#else
    const T_slice* operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
#endif

    //
    // Additional ORBacus specific functions
    //
    T_slice** data() { return data_; }
    T_slice* const * data() const { return data_; }

    void consume(OBBndFixArraySeq<T_slice, T, n, max>&);
};

//
// Template for variable-length array unbounded sequence type
//
template<class T_slice, class T, CORBA_ULong n>
class OBVarArraySeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_Boolean rel_;
    T_slice** data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T_slice** allocbuf(CORBA_ULong);
    static void freebuf(T_slice**);

    OBVarArraySeq();
    OBVarArraySeq(CORBA_ULong);
    OBVarArraySeq(CORBA_ULong, CORBA_ULong, T_slice**, CORBA_Boolean = false);
    OBVarArraySeq(const OBVarArraySeq<T_slice, T, n>&);
    ~OBVarArraySeq() { if(rel_) freebuf(data_); }

    OBVarArraySeq<T_slice, T, n>&
    operator=(const OBVarArraySeq<T_slice, T, n>&);

    CORBA_ULong maximum() const { return max_; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef T_slice*& SubType;
    typedef const T_slice* ConstSubType;

    T_slice*& operator[](CORBA_ULong idx)
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
#ifdef HAVE_VCPLUSPLUS_BUGS
    const T_slice* operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange);
      return (const T_slice*)data_[idx]; }
#else
    const T_slice* operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
#endif

    //
    // Additional ORBacus specific functions
    //
    T_slice** data() { return data_; }
    T_slice* const * data() const { return data_; }

    void consume(OBVarArraySeq<T_slice, T, n>&);
};

//
// Template for variable-length array bounded sequence type
//
template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
class OBBndVarArraySeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_Boolean rel_;
    T_slice** data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T_slice** allocbuf(CORBA_ULong);
    static void freebuf(T_slice**);

    OBBndVarArraySeq();
    OBBndVarArraySeq(CORBA_ULong, T_slice**, CORBA_Boolean = false);
    OBBndVarArraySeq(const OBBndVarArraySeq<T_slice, T, n, max>&);
    ~OBBndVarArraySeq() { if(rel_) freebuf(data_); }

    OBBndVarArraySeq<T_slice, T, n, max>&
    operator=(const OBBndVarArraySeq<T_slice, T, n, max>&);

    CORBA_ULong maximum() const { return max; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef T_slice*& SubType;
    typedef const T_slice* ConstSubType;

    T_slice*& operator[](CORBA_ULong idx)
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
#ifdef HAVE_VCPLUSPLUS_BUGS
    const T_slice* operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange);
      return (const T_slice*)data_[idx]; }
#else
    const T_slice* operator[](CORBA_ULong idx) const
    { assert_nca(idx < len_, OBNCASeqRange); return data_[idx]; }
#endif

    //
    // Additional ORBacus specific functions
    //
    T_slice** data() { return data_; }
    T_slice* const * data() const { return data_; }

    void consume(OBBndVarArraySeq<T_slice, T, n, max>&);
};

//
// Template for unbounded object reference sequence type
//
template<class T>
class OBObjSeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_ULong off_;
    CORBA_Boolean rel_;
    T** data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T** allocbuf(CORBA_ULong);
    static void freebuf(T**);

    OBObjSeq();
    OBObjSeq(CORBA_ULong);
    OBObjSeq(CORBA_ULong, CORBA_ULong, T**, CORBA_Boolean = false);
    OBObjSeq(const OBObjSeq<T>&);
    ~OBObjSeq() { if(rel_) freebuf(data_); }

    OBObjSeq<T>& operator=(const OBObjSeq<T>&);

    CORBA_ULong maximum() const { return max_; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef OBObjForSeq<T> SubType;
    typedef OBObjForSeq<T> ConstSubType;

    //
    // TODO: This must be changed - I need a const and a non-const
    // version of this operator. But the problem is that the following
    // code does not work with all compilers (for example not with SGI
    // CC 7.1):
    //
    // const OBObjForSeq<T> operator[](CORBA_ULong idx) const
    //
    OBObjForSeq<T> operator[](CORBA_ULong idx) const
    {
	assert_nca(idx < len_, OBNCASeqRange);
	return OBObjForSeq<T>(&data_[idx + off_], rel_);
    }

    //
    // Additional ORBacus specific functions
    //
    T** data() { return data_ + off_; }
    T* const * data() const { return data_ + off_; }

private:

    //
    // Make sure that widening between object reference _var types
    // require a call to _duplicate()
    //
    void insert(const OBObjBase&) { }
    void append(const OBObjBase&) { }

public:

    void insert(T*);
    void insert(const OBObjVar<T>&);
    void insert(const OBObjForSeq<T>&);
    void append(T*);
    void append(const OBObjVar<T>&);
    void append(const OBObjForSeq<T>&);
    void remove(CORBA_ULong);

    void consume(OBObjSeq<T>&);
};

//
// Template for bounded object reference sequence type
//
template<class T, CORBA_ULong max>
class OBBndObjSeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_Boolean rel_;
    T** data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static T** allocbuf(CORBA_ULong);
    static void freebuf(T**);

    OBBndObjSeq();
    OBBndObjSeq(CORBA_ULong, T**, CORBA_Boolean = false);
    OBBndObjSeq(const OBBndObjSeq<T, max>&);
    ~OBBndObjSeq() { if(rel_) freebuf(data_); }

    OBBndObjSeq<T, max>& operator=(const OBBndObjSeq<T, max>&);

    CORBA_ULong maximum() const { return max; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef OBObjForSeq<T> SubType;
    typedef OBObjForSeq<T> ConstSubType;

    //
    // TODO: See the comments in OBObjSeq
    //
    OBObjForSeq<T> operator[](CORBA_ULong idx) const
    {
	assert_nca(idx < len_, OBNCASeqRange);
	return OBObjForSeq<T>(&data_[idx], rel_);
    }

    //
    // Additional ORBacus specific functions
    //
    T** data() { return data_; }
    T* const * data() const { return data_; }

    void consume(OBBndObjSeq<T, max>&);
};

//
// Unbounded string sequence type
//
// (Not a template, but it is similiar to the other sequence types,
//  therefore it's definition is in this file)
//
class OBStrSeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_ULong off_;
    CORBA_Boolean rel_;
    char** data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static char** allocbuf(CORBA_ULong);
    static void freebuf(char**);

    OBStrSeq();
    OBStrSeq(CORBA_ULong);
    OBStrSeq(CORBA_ULong, CORBA_ULong, char**, CORBA_Boolean = false);
    OBStrSeq(const OBStrSeq&);
    ~OBStrSeq() { if(rel_) freebuf(data_); }

    OBStrSeq& operator=(const OBStrSeq&);

    CORBA_ULong maximum() const { return max_; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef OBStrForSeq SubType;
    typedef const char* ConstSubType;

    OBStrForSeq operator[](CORBA_ULong idx)
    {
	assert_nca(idx < len_, OBNCASeqRange);
	return OBStrForSeq(&data_[idx + off_], rel_);
    }

    const char* operator[](CORBA_ULong idx) const
    {
	assert_nca(idx < len_, OBNCASeqRange);
	return data_[idx + off_];
    }

    //
    // Additional ORBacus specific functions
    //
    char** data() { return data_ + off_; }
    char* const * data() const { return data_ + off_; }

    void insert(char*);
    void insert(const char* p) { insert(CORBA_string_dup(p)); }
    void insert(const CORBA_String_var& r) { insert(CORBA_string_dup(r)); }
    void insert(const OBStrForSeq& r) { insert(CORBA_string_dup(r)); }

    void append(char*);
    void append(const char* p) { append(CORBA_string_dup(p)); }
    void append(const CORBA_String_var& r) { append(CORBA_string_dup(r)); }
    void append(const OBStrForSeq& r) { append(CORBA_string_dup(r)); }

    void remove(CORBA_ULong);

    void consume(OBStrSeq&);
};

//
// Template for bounded string sequence type
//
template<CORBA_ULong max>
class OBBndStrSeq
{
    CORBA_ULong max_;
    CORBA_ULong len_;
    CORBA_Boolean rel_;
    char** data_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    static char** allocbuf(CORBA_ULong n)
    { return OBStrSeq::allocbuf(n); }
    static void freebuf(char** p)
    { OBStrSeq::freebuf(p); }

    OBBndStrSeq();
    OBBndStrSeq(CORBA_ULong, char**, CORBA_Boolean = false);
    OBBndStrSeq(const OBBndStrSeq<max>&);
    ~OBBndStrSeq() { if(rel_) freebuf(data_); }

    OBBndStrSeq<max>& operator=(const OBBndStrSeq<max>&);

    CORBA_ULong maximum() const { return max; }

    void length(CORBA_ULong);
    CORBA_ULong length() const { return len_; }

    typedef OBStrForSeq SubType;
    typedef const char* ConstSubType;

    OBStrForSeq operator[](CORBA_ULong idx)
    {
	assert_nca(idx < len_, OBNCASeqRange);
	return OBStrForSeq(&data_[idx], rel_);
    }

    const char* operator[](CORBA_ULong idx) const
    {
	assert_nca(idx < len_, OBNCASeqRange);
	return data_[idx];
    }

    //
    // Additional ORBacus specific functions
    //
    char** data() { return data_; }
    char* const * data() const { return data_; }

    void consume(OBBndStrSeq<max>&);
};

// ----------------------------------------------------------------------
// CDR for basic sequence types
// ----------------------------------------------------------------------

void OBMarshal(const OBFixSeq< OBUnsignedChar >&, CORBA_Octet*&);
void OBMarshalCount(const OBFixSeq< OBUnsignedChar >&, CORBA_ULong&);
void OBUnmarshal(OBFixSeq< OBUnsignedChar >&, const CORBA_Octet*&, bool);

void OBMarshal(const OBVarSeq< OBFixSeq< OBUnsignedChar > >&, CORBA_Octet*&);
void OBMarshalCount(const OBVarSeq< OBFixSeq< OBUnsignedChar > >&,
		    CORBA_ULong&);
void OBUnmarshal(OBVarSeq< OBFixSeq< OBUnsignedChar > >&, const CORBA_Octet*&,
		 bool);

void OBMarshal(const OBFixSeq< CORBA_Short >&, CORBA_Octet*&);
void OBMarshalCount(const OBFixSeq< CORBA_Short >&, CORBA_ULong&);
void OBUnmarshal(OBFixSeq< CORBA_Short >&, const CORBA_Octet*&, bool);

void OBMarshal(const OBFixSeq< CORBA_UShort >&, CORBA_Octet*&);
void OBMarshalCount(const OBFixSeq< CORBA_UShort >&, CORBA_ULong&);
void OBUnmarshal(OBFixSeq< CORBA_UShort >&, const CORBA_Octet*&, bool);

void OBMarshal(const OBFixSeq< CORBA_Long >&, CORBA_Octet*&);
void OBMarshalCount(const OBFixSeq< CORBA_Long >&, CORBA_ULong&);
void OBUnmarshal(OBFixSeq< CORBA_Long >&, const CORBA_Octet*&, bool);

void OBMarshal(const OBFixSeq< CORBA_ULong >&, CORBA_Octet*&);
void OBMarshalCount(const OBFixSeq< CORBA_ULong >&, CORBA_ULong&);
void OBUnmarshal(OBFixSeq< CORBA_ULong >&, const CORBA_Octet*&, bool);

void OBMarshal(const OBFixSeq< CORBA_Float >&, CORBA_Octet*&);
void OBMarshalCount(const OBFixSeq< CORBA_Float >&, CORBA_ULong&);
void OBUnmarshal(OBFixSeq< CORBA_Float >&, const CORBA_Octet*&, bool);

void OBMarshal(const OBFixSeq< CORBA_Double >&, CORBA_Octet*&);
void OBMarshalCount(const OBFixSeq< CORBA_Double >&, CORBA_ULong&);
void OBUnmarshal(OBFixSeq< CORBA_Double >&, const CORBA_Octet*&, bool);

void OBMarshal(const OBStrSeq&, CORBA_Octet*&);
void OBMarshalCount(const OBStrSeq&, CORBA_ULong&);
void OBUnmarshal(OBStrSeq&, const CORBA_Octet*&, bool);

// ----------------------------------------------------------------------
// Constructed type info class (for use with the any type)
// ----------------------------------------------------------------------

class OBConstructedInfo
{
    //
    // Prevent usage of copy constructor and asignment and
    // equality operators
    //
    OBConstructedInfo(const OBConstructedInfo&);
    void operator=(const OBConstructedInfo&);
    void operator==(const OBConstructedInfo&);

public:

    OBConstructedInfo() { };
    virtual ~OBConstructedInfo() { };

    //
    // void* memory handling
    //
    virtual void* alloc() const = 0;
    virtual void free(void*) const = 0;
    virtual void* dup(const void*) const = 0;

    //
    // CDR
    //
    virtual void marshal(const void*, CORBA_Octet*&) const = 0;
    virtual void marshalCount(const void*, CORBA_ULong&) const = 0;
    virtual void unmarshal(void*, const CORBA_Octet*&, bool) const = 0;
};

#if defined(HAVE_NO_EXPLICIT_TEMPLATES) && !defined(HAVE_PRAGMA_DEFINE)
#   include "OB/TemplateI.h"
#endif

#endif
