mirror of https://github.com/qt/qtdatavis3d.git
750 lines
20 KiB
C++
750 lines
20 KiB
C++
/****************************************************************************
|
|
* *
|
|
* OpenNI 1.x Alpha *
|
|
* Copyright (C) 2011 PrimeSense Ltd. *
|
|
* *
|
|
* This file is part of OpenNI. *
|
|
* *
|
|
* OpenNI is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Lesser General Public License as published *
|
|
* by the Free Software Foundation, either version 3 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* OpenNI is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public License *
|
|
* along with OpenNI. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
****************************************************************************/
|
|
#ifndef _XN_LIST_H
|
|
#define _XN_LIST_H
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Includes
|
|
//---------------------------------------------------------------------------
|
|
#include <XnDataTypes.h>
|
|
#include <IXnNodeAllocator.h>
|
|
#include <XnNodeAllocator.h>
|
|
#include <XnNode.h>
|
|
#include <XnStatusCodes.h>
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Types
|
|
//---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* The linked list
|
|
*/
|
|
class XnList
|
|
{
|
|
public:
|
|
class ConstIterator
|
|
{
|
|
public:
|
|
friend class XnList;
|
|
|
|
/**
|
|
* Copy constructor
|
|
*
|
|
* @param other [in] instance to copy from
|
|
*/
|
|
ConstIterator(const ConstIterator& other) : m_pCurrent(other.m_pCurrent) {}
|
|
|
|
/**
|
|
* Support ++iterator, go to the next object in the list
|
|
*/
|
|
ConstIterator& operator++()
|
|
{
|
|
m_pCurrent = m_pCurrent->Next();
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Support iterator++, go to the next object in the list, returning the old value
|
|
*/
|
|
ConstIterator operator++(int)
|
|
{
|
|
ConstIterator other(m_pCurrent);
|
|
m_pCurrent = m_pCurrent->Next();
|
|
return other;
|
|
}
|
|
|
|
/**
|
|
* Support --iterator, go to the next object in the list
|
|
*/
|
|
ConstIterator& operator--()
|
|
{
|
|
m_pCurrent = m_pCurrent->Previous();
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Support iterator--, go to the next object in the list, returning the old value
|
|
*/
|
|
ConstIterator operator--(int)
|
|
{
|
|
ConstIterator other = *this;
|
|
--*this;
|
|
return other;
|
|
}
|
|
|
|
/**
|
|
* Operator to check if 2 iterators point to the same object
|
|
*
|
|
* @param other [in] instance to compare with
|
|
*/
|
|
XnBool operator==(const ConstIterator& other) const
|
|
{
|
|
return m_pCurrent == other.m_pCurrent;
|
|
}
|
|
/**
|
|
* Operator to check if 2 iterators point to different objects
|
|
*
|
|
* @param other [in] instance to compare with
|
|
*/
|
|
XnBool operator!=(const ConstIterator& other) const
|
|
{
|
|
return m_pCurrent != other.m_pCurrent;
|
|
}
|
|
|
|
/**
|
|
* Get the value of the current object (const version)
|
|
*/
|
|
const XnValue& operator*() const
|
|
{
|
|
return m_pCurrent->Data();
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the entire current object (const version)
|
|
*/
|
|
const XnNode* GetNode() const
|
|
{
|
|
return m_pCurrent;
|
|
}
|
|
|
|
/**
|
|
* Get the entire current object (non-const version)
|
|
*/
|
|
XnNode* GetNode()
|
|
{
|
|
return m_pCurrent;
|
|
}
|
|
|
|
protected:
|
|
/**
|
|
* constructor to be used from inside the XnList. It points to the node supplied.
|
|
*
|
|
* @param pNode [in] The XnNode to which to currently point
|
|
*/
|
|
ConstIterator(XnNode* pNode) : m_pCurrent(pNode) {}
|
|
|
|
/** The current XnNode */
|
|
XnNode* m_pCurrent;
|
|
};
|
|
|
|
/**
|
|
* Iterator to the XnList
|
|
*/
|
|
class Iterator : public ConstIterator
|
|
{
|
|
public:
|
|
friend class XnList;
|
|
|
|
/**
|
|
* Copy constructor
|
|
*
|
|
* @param other [in] instance to copy from
|
|
*/
|
|
inline Iterator(const Iterator& other) : ConstIterator(other) {}
|
|
|
|
/**
|
|
* Support ++iterator, go to the next object in the list
|
|
*/
|
|
inline Iterator& operator++()
|
|
{
|
|
++(*(ConstIterator*)this);
|
|
return (*this);
|
|
}
|
|
/**
|
|
* Support iterator++, go to the next object in the list, returning the old value
|
|
*/
|
|
inline Iterator operator++(int)
|
|
{
|
|
Iterator result = *this;
|
|
++*this;
|
|
return (result);
|
|
}
|
|
|
|
/**
|
|
* Support --iterator, go to the next object in the list
|
|
*/
|
|
inline Iterator& operator--()
|
|
{
|
|
--(*(ConstIterator*)this);
|
|
return (*this);
|
|
}
|
|
/**
|
|
* Support iterator--, go to the next object in the list, returning the old value
|
|
*/
|
|
inline Iterator operator--(int)
|
|
{
|
|
Iterator result = *this;
|
|
--*this;
|
|
return (result);
|
|
}
|
|
|
|
/**
|
|
* Get the value of the current object
|
|
*/
|
|
inline XnValue& operator*() const { return ((XnValue&)**(ConstIterator*)this); }
|
|
|
|
protected:
|
|
/**
|
|
* constructor to be used from inside the XnList. It points to the node supplied.
|
|
*
|
|
* @param pNode [in] The XnNode to which to currently point
|
|
*/
|
|
inline Iterator(XnNode* pNode) : ConstIterator(pNode) {}
|
|
};
|
|
|
|
public:
|
|
/**
|
|
* Constructor. Initialize internal representations
|
|
*/
|
|
XnList()
|
|
{
|
|
//Default node allocator is XnNodeAllocator
|
|
Init(XN_NEW(XnNodeAllocator));
|
|
m_bOwnsAllocator = TRUE;
|
|
}
|
|
|
|
/**
|
|
* Destructor. Destroy internal representations
|
|
*/
|
|
virtual ~XnList()
|
|
{
|
|
Clear();
|
|
|
|
// Return base node to the pool
|
|
m_pNodeAllocator->Deallocate(m_pBase);
|
|
|
|
if (m_bOwnsAllocator)
|
|
{
|
|
//We created the allocator in this object, so we must release it
|
|
XN_DELETE(m_pNodeAllocator);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add a new value at the beginning of list
|
|
*
|
|
* @param value [in] The value to add to the head of the list
|
|
*
|
|
* @return XN_STATUS_ALLOC_FAILED Failed to add to the list because no nodes are available.
|
|
*/
|
|
XnStatus AddFirst(const XnValue& value)
|
|
{
|
|
return Add(m_pBase, value);
|
|
}
|
|
|
|
/**
|
|
* Add a new value at the end of the list
|
|
*
|
|
* @param value [in] The value to add to the tail of the list
|
|
*
|
|
* @return XN_STATUS_ALLOC_FAILED Failed to add to the list because no nodes are available.
|
|
*/
|
|
XnStatus AddLast(const XnValue& value)
|
|
{
|
|
return Add(rbegin().m_pCurrent, value);
|
|
}
|
|
|
|
/**
|
|
* Add a new value after the object pointed to by the iterator
|
|
*
|
|
* @param where [in] iterator to the position after which to add the new value
|
|
* @param val [in] The value to add to the list
|
|
*
|
|
* @return XN_STATUS_ALLOC_FAILED Failed to add to the list because no nodes are available,
|
|
* XN_STATUS_ILLEGAL_POSITION iterator is invalid
|
|
*/
|
|
XnStatus AddAfter(ConstIterator where, const XnValue& val)
|
|
{
|
|
if (where == end())
|
|
{
|
|
return XN_STATUS_ILLEGAL_POSITION;
|
|
}
|
|
|
|
return Add(where.m_pCurrent, val);
|
|
}
|
|
|
|
/**
|
|
* Add a new value before the object pointed to by the iterator
|
|
*
|
|
* @param where [in] iterator to the position before which to add the new value
|
|
* @param val [in] The value to add to the list
|
|
*
|
|
* @return XN_STATUS_ALLOC_FAILED Failed to add to the list because no nodes are available,
|
|
*/
|
|
XnStatus AddBefore(ConstIterator where, const XnValue& val)
|
|
{
|
|
if (where == end())
|
|
{
|
|
return XN_STATUS_ILLEGAL_POSITION;
|
|
}
|
|
|
|
return Add(where.m_pCurrent->Previous(), val);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get an iterator pointing to a value in the list.
|
|
*
|
|
* @param value [in] The searched value
|
|
*
|
|
* @return end() if value doesn't exist
|
|
*/
|
|
Iterator Find(const XnValue& value)
|
|
{
|
|
if (IsEmpty())
|
|
{
|
|
return end();
|
|
}
|
|
|
|
Iterator iter = begin();
|
|
for (; iter != end(); ++iter)
|
|
{
|
|
if (*iter == value)
|
|
break;
|
|
}
|
|
return iter;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get an iterator pointing to a value in the list.
|
|
*
|
|
* @param value [in] The searched value
|
|
*
|
|
* @return end() if value doesn't exist
|
|
*/
|
|
ConstIterator Find(const XnValue& value) const
|
|
{
|
|
if (IsEmpty())
|
|
{
|
|
return end();
|
|
}
|
|
|
|
ConstIterator iter = begin();
|
|
for (; iter != end(); ++iter)
|
|
{
|
|
if (*iter == value)
|
|
break;
|
|
}
|
|
return iter;
|
|
}
|
|
|
|
|
|
/**
|
|
* Remove a value from the list
|
|
*
|
|
* @param where [in] Iterator pointing to an entry in the list
|
|
* @param value [out] The value that was in the removed entry
|
|
*
|
|
* @return XN_STATUS_ILLEGAL_POSITION iterator was invalid
|
|
*/
|
|
XnStatus Remove(ConstIterator where, XnValue& value)
|
|
{
|
|
value = *where;
|
|
return Remove(where);
|
|
}
|
|
|
|
/**
|
|
* Remove a value from the list
|
|
*
|
|
* @param where [in] Iterator pointing to an entry in the list
|
|
*
|
|
* @return XN_STATUS_ILLEGAL_POSITION iterator was invalid
|
|
*/
|
|
virtual XnStatus Remove(ConstIterator where)
|
|
{
|
|
// Verify iterator is valid
|
|
if (where == end())
|
|
{
|
|
return XN_STATUS_ILLEGAL_POSITION;
|
|
}
|
|
if (IsEmpty())
|
|
{
|
|
return XN_STATUS_IS_EMPTY;
|
|
}
|
|
|
|
XnNode* pToRemove = where.m_pCurrent;
|
|
|
|
// Connect other nodes to bypass the one removed
|
|
pToRemove->Previous()->Next() = pToRemove->Next();
|
|
pToRemove->Next()->Previous() = pToRemove->Previous();
|
|
|
|
// Return removed node to the pool
|
|
m_pNodeAllocator->Deallocate(pToRemove);
|
|
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
* Remove all entries from the list
|
|
*/
|
|
XnStatus Clear()
|
|
{
|
|
while (!IsEmpty())
|
|
Remove(begin());
|
|
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* Check if list is empty
|
|
*/
|
|
XnBool IsEmpty() const
|
|
{
|
|
return (begin() == end());
|
|
}
|
|
|
|
/**
|
|
* Current size of the list
|
|
*/
|
|
XnUInt32 Size() const
|
|
{
|
|
XnUInt32 nSize = 0;
|
|
for (ConstIterator iter = begin(); iter != end(); ++iter, ++nSize)
|
|
;
|
|
|
|
return nSize;
|
|
}
|
|
|
|
/**
|
|
* An iterator to the first entry of the list (non-const version)
|
|
*/
|
|
Iterator begin()
|
|
{
|
|
return Iterator(m_pBase->Next());
|
|
}
|
|
|
|
/**
|
|
* An iterator to the first entry of the list (const version)
|
|
*/
|
|
ConstIterator begin() const
|
|
{
|
|
return ConstIterator(m_pBase->Next());
|
|
}
|
|
|
|
/**
|
|
* An iterator 1to the end of the list (non-const version). The position is invalid.
|
|
*/
|
|
Iterator end()
|
|
{
|
|
return Iterator(m_pBase);
|
|
}
|
|
|
|
/**
|
|
* An iterator to the end of the list (const version). The position is invalid.
|
|
*/
|
|
ConstIterator end() const
|
|
{
|
|
return ConstIterator(m_pBase);
|
|
}
|
|
|
|
/**
|
|
* An iterator to the last entry of the list (non-const version)
|
|
*/
|
|
Iterator rbegin()
|
|
{
|
|
return Iterator(m_pBase->Previous());
|
|
}
|
|
|
|
/**
|
|
* An iterator to the last entry of the list (const version)
|
|
*/
|
|
ConstIterator rbegin() const
|
|
{
|
|
return ConstIterator(m_pBase->Previous());
|
|
}
|
|
|
|
/**
|
|
* An iterator to the beginning of the list (non-const version). This position is invalid
|
|
*/
|
|
Iterator rend()
|
|
{
|
|
return Iterator(m_pBase);
|
|
}
|
|
|
|
/**
|
|
* An iterator to the beginning of the list (const version). This position is invalid
|
|
*/
|
|
ConstIterator rend() const
|
|
{
|
|
return ConstIterator(m_pBase);
|
|
}
|
|
|
|
protected:
|
|
friend class XnNodeManager;
|
|
|
|
/**
|
|
* Constructor. Initialize internal representations
|
|
*/
|
|
XnList(INiNodeAllocator* pNodeAllocator)
|
|
{
|
|
Init(pNodeAllocator);
|
|
m_bOwnsAllocator = FALSE;
|
|
}
|
|
|
|
void Init(INiNodeAllocator* pNodeAllocator)
|
|
{
|
|
m_pNodeAllocator = pNodeAllocator;
|
|
// Allocate a node to act as base node.
|
|
m_pBase = m_pNodeAllocator->Allocate();
|
|
if (m_pBase == NULL)
|
|
{
|
|
// OZOZ: Allocation failed in ctor...
|
|
}
|
|
|
|
m_pBase->Next() = m_pBase->Previous() = m_pBase;
|
|
}
|
|
|
|
/**
|
|
* Add a new value to the list
|
|
*
|
|
* @param pWhere [in] The XnNode after which to add the new value
|
|
* @param val [in] The value to add to the list
|
|
*
|
|
* @return XN_STATUS_ALLOC_FAILED Failed to add to the list because no nodes are available,
|
|
*/
|
|
XnStatus Add(XnNode* pWhere, const XnValue& val)
|
|
{
|
|
// Get a node from the pool for the entry
|
|
XnNode* pNewNode = m_pNodeAllocator->Allocate();
|
|
if (pNewNode == NULL)
|
|
{
|
|
return XN_STATUS_ALLOC_FAILED;
|
|
}
|
|
// push new node to position
|
|
pNewNode->Data() = val;
|
|
pNewNode->Next() = pWhere->Next();
|
|
pNewNode->Previous() = pWhere;
|
|
pWhere->Next()->Previous() = pNewNode;
|
|
pWhere->Next() = pNewNode;
|
|
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
|
|
/** The base node for the list */
|
|
XnNode* m_pBase;
|
|
|
|
INiNodeAllocator* m_pNodeAllocator;
|
|
XnBool m_bOwnsAllocator;
|
|
|
|
private:
|
|
XN_DISABLE_COPY_AND_ASSIGN(XnList);
|
|
};
|
|
|
|
/**
|
|
* Declares a list of type @a Type, which is named @a ClassName. The list uses translator @a Translator,
|
|
* and is declared using the @a decl declspec.
|
|
*/
|
|
#define XN_DECLARE_LIST_WITH_TRANSLATOR_DECL(decl, Type, ClassName, Translator) \
|
|
class decl ClassName : public XnList \
|
|
{ \
|
|
public: \
|
|
class decl ConstIterator : public XnList::ConstIterator \
|
|
{ \
|
|
public: \
|
|
friend class ClassName; \
|
|
inline ConstIterator(const ConstIterator& other) : XnList::ConstIterator(other) {} \
|
|
inline ConstIterator& operator++() \
|
|
{ \
|
|
++(*(XnList::ConstIterator*)this); \
|
|
return (*this); \
|
|
} \
|
|
inline ConstIterator operator++(int) \
|
|
{ \
|
|
ConstIterator result = *this; \
|
|
++*this; \
|
|
return result; \
|
|
} \
|
|
inline ConstIterator& operator--() \
|
|
{ \
|
|
--(*(XnList::ConstIterator*)this); \
|
|
return (*this); \
|
|
} \
|
|
inline ConstIterator operator--(int) \
|
|
{ \
|
|
ConstIterator result = *this; \
|
|
--*this; \
|
|
return result; \
|
|
} \
|
|
inline Type const& operator*() const \
|
|
{ \
|
|
return Translator::GetFromValue(**((XnList::ConstIterator*)this)); \
|
|
} \
|
|
inline Type const* operator->() const { return (&**this); } \
|
|
protected: \
|
|
inline ConstIterator(XnNode* pNode) : XnList::ConstIterator(pNode) {} \
|
|
inline ConstIterator(const XnList::ConstIterator& other) : \
|
|
XnList::ConstIterator(other) \
|
|
{} \
|
|
}; \
|
|
class decl Iterator : public ConstIterator \
|
|
{ \
|
|
public: \
|
|
friend class ClassName; \
|
|
Iterator(const Iterator& other) : ConstIterator(other) {} \
|
|
inline Iterator& operator++() \
|
|
{ \
|
|
++(*(ConstIterator*)this); \
|
|
return (*this); \
|
|
} \
|
|
inline Iterator operator++(int) \
|
|
{ \
|
|
Iterator result = *this; \
|
|
++*this; \
|
|
return result; \
|
|
} \
|
|
inline Iterator& operator--() \
|
|
{ \
|
|
--(*(ConstIterator*)this); \
|
|
return (*this); \
|
|
} \
|
|
inline Iterator operator--(int) \
|
|
{ \
|
|
Iterator result = *this; \
|
|
--*this; \
|
|
return result; \
|
|
} \
|
|
inline Type& operator*() const { return ((Type&)**(ConstIterator*)this); } \
|
|
inline Type* operator->() const { return (&**this); } \
|
|
protected: \
|
|
inline Iterator(XnNode* pNode) : ConstIterator(pNode) {} \
|
|
inline Iterator(const XnList::Iterator& other) : ConstIterator(other) {} \
|
|
}; \
|
|
public: \
|
|
ClassName() \
|
|
{ \
|
|
} \
|
|
~ClassName() \
|
|
{ \
|
|
while (!IsEmpty()) \
|
|
Remove(begin()); \
|
|
} \
|
|
inline XnStatus AddFirst(Type const& value) \
|
|
{ \
|
|
XnValue val = Translator::CreateValueCopy(value); \
|
|
XnStatus nRetVal = XnList::AddFirst(val); \
|
|
if (nRetVal != XN_STATUS_OK) \
|
|
{ \
|
|
Translator::FreeValue(val); \
|
|
return (nRetVal); \
|
|
} \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
inline XnStatus AddLast(Type const& value) \
|
|
{ \
|
|
XnValue val = Translator::CreateValueCopy(value); \
|
|
XnStatus nRetVal = XnList::AddLast(val); \
|
|
if (nRetVal != XN_STATUS_OK) \
|
|
{ \
|
|
Translator::FreeValue(val); \
|
|
return (nRetVal); \
|
|
} \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
inline XnStatus AddAfter(ConstIterator where, Type const& value) \
|
|
{ \
|
|
XnValue val = Translator::CreateValueCopy(value); \
|
|
XnStatus nRetVal = XnList::AddAfter(where, val); \
|
|
if (nRetVal != XN_STATUS_OK) \
|
|
{ \
|
|
Translator::FreeValue(val); \
|
|
return (nRetVal); \
|
|
} \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
inline XnStatus AddBefore(ConstIterator where, Type const& value) \
|
|
{ \
|
|
XnValue val = Translator::CreateValueCopy(value); \
|
|
XnStatus nRetVal = XnList::AddBefore(where, val); \
|
|
if (nRetVal != XN_STATUS_OK) \
|
|
{ \
|
|
Translator::FreeValue(val); \
|
|
return (nRetVal); \
|
|
} \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
inline ConstIterator Find(Type const& value) const \
|
|
{ \
|
|
XnValue _value = Translator::GetAsValue(value); \
|
|
return XnList::Find(_value); \
|
|
} \
|
|
inline Iterator Find(Type const& value) \
|
|
{ \
|
|
XnValue _value = Translator::GetAsValue(value); \
|
|
return XnList::Find(_value); \
|
|
} \
|
|
inline XnStatus Remove(ConstIterator where) \
|
|
{ \
|
|
XnValue val = Translator::GetAsValue(*where); \
|
|
XnStatus nRetVal = XnList::Remove(where); \
|
|
if (nRetVal != XN_STATUS_OK) return (nRetVal); \
|
|
Translator::FreeValue(val); \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
inline XnStatus Remove(Type const& value) \
|
|
{ \
|
|
Iterator it = Find(value); \
|
|
return Remove(it); \
|
|
} \
|
|
inline Iterator begin() { return XnList::begin(); } \
|
|
inline ConstIterator begin() const { return XnList::begin(); } \
|
|
inline Iterator end() { return XnList::end(); } \
|
|
inline ConstIterator end() const { return XnList::end(); } \
|
|
inline Iterator rbegin() { return XnList::rbegin(); } \
|
|
inline ConstIterator rbegin() const { return XnList::rbegin(); } \
|
|
inline Iterator rend() { return XnList::rend(); } \
|
|
inline ConstIterator rend() const { return XnList::rend(); } \
|
|
protected: \
|
|
virtual XnStatus Remove(XnList::ConstIterator where) \
|
|
{ \
|
|
return Remove(ConstIterator(where)); \
|
|
} \
|
|
private: \
|
|
XN_DISABLE_COPY_AND_ASSIGN(ClassName); \
|
|
};
|
|
|
|
/**
|
|
* Declares a list of type @a Type, which is named @a ClassName. The list uses translator @a Translator.
|
|
*/
|
|
#define XN_DECLARE_LIST_WITH_TRANSLATOR(Type, ClassName, Translator) \
|
|
XN_DECLARE_LIST_WITH_TRANSLATOR_DECL(, Type, ClassName, Translator)
|
|
|
|
/**
|
|
* Declares a list of type @a Type, which is named @a ClassName. The list uses creates a default translator
|
|
* and is declared using the @a decl declspec.
|
|
*/
|
|
#define XN_DECLARE_LIST_DECL(decl, Type, ClassName) \
|
|
XN_DECLARE_DEFAULT_VALUE_TRANSLATOR_DECL(decl, Type, XN_DEFAULT_TRANSLATOR_NAME(ClassName)) \
|
|
XN_DECLARE_LIST_WITH_TRANSLATOR_DECL(decl, Type, ClassName, XN_DEFAULT_TRANSLATOR_NAME(ClassName))
|
|
|
|
/**
|
|
* Declares a list of type @a Type, which is named @a ClassName. The list uses creates a default translator.
|
|
*/
|
|
#define XN_DECLARE_LIST(Type, ClassName) \
|
|
XN_DECLARE_LIST_DECL(, Type, ClassName)
|
|
|
|
#endif // _XN_LIST_H
|
|
|