/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
****************************************************************************/

#pragma once

#include "glmAbstractAttribute.h"
#include "glmBinaryStream.h"
#include "glmXMLStream.h"

namespace glm
{
    // template class for inspectable attributes through pointer to value, const reference and const pointer accessors.
    template <class TValue, class TOwner>
    class ContainerAccessorsAttribute : public AbstractAttributeT<TValue, TOwner>
    {
        GLM_VIRTUAL_RTTI_T0_T1("34d83975-ea9f-47f6-811a-0fb0d7025e07", glm::ContainerAccessorsAttribute, TValue, TOwner, addBaseClasses)

    public:
        typedef TValue (TOwner::*Getter)(unsigned int index) const;       // Getter function for primitive data types
        typedef void (TOwner::*Setter)(unsigned int index, TValue value); // Setter function for primitive data types

        typedef TValue value_type;

        ContainerAccessorsAttribute(const char* name, TValue (TOwner::*getter)(unsigned int index) const, void (TOwner::*setter)(unsigned int index, TValue value), unsigned int index);
        ContainerAccessorsAttribute(const ContainerAccessorsAttribute& attribute);
        virtual ~ContainerAccessorsAttribute();

        const ContainerAccessorsAttribute& operator=(const ContainerAccessorsAttribute& attribute);

        // Inherited
        virtual TValue getValue(const TOwner& owner) const;
        virtual void setValue(TOwner& owner, TValue value) const;
        virtual const RTTI& getAttributeRTTI() const;

        static const RTTI& getAttributeClassRTTI();
        static void createAttributeRTTI();
        static void destroyAttributeRTTI();

    private:
        // Inherited
        virtual void pack(BinaryStream& stream, const void* owner) const;
        virtual void unpack(BinaryStream& stream, void* owner) const;
        virtual void pack(XMLStream& stream, DataItem& configurationItem, const void* owner) const;
        virtual void unpack(XMLStream& stream, const DataItem& configurationItem, void* owner) const;

        static void addBaseClasses();
        ContainerAccessorsAttribute()
        {
        }

        Getter _getter;      // pointer to the owner's get accessor to the attribute value
        Setter _setter;      // pointer to the owner's set accessor to the attribute value
        unsigned int _index; // container index
    };

    template <class TValue, class TOwner>
    RTTI* ContainerAccessorsAttribute<TValue, TOwner>::_rtti(NULL);

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    void ContainerAccessorsAttribute<TValue, TOwner>::addBaseClasses()
    {
        ContainerAccessorsAttribute<TValue, TOwner>::getClassRTTI().template addBaseClass<AbstractAttributeT<TValue, TOwner>>();
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    ContainerAccessorsAttribute<TValue, TOwner>::ContainerAccessorsAttribute(const char* name, TValue (TOwner::*getter)(unsigned int index) const, void (TOwner::*setter)(unsigned int index, TValue value), unsigned int index)
        : AbstractAttributeT<TValue, TOwner>(name, &TOwner::getClassRTTI())
        , _getter(static_cast<Getter>(getter))
        , _setter(static_cast<Setter>(setter))
        , _index(index)
    {
        GLM_DEBUG_ASSERT((_getter != NULL) && (_setter != NULL));
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    ContainerAccessorsAttribute<TValue, TOwner>::ContainerAccessorsAttribute(const ContainerAccessorsAttribute& attribute)
        : AbstractAttributeT<TValue, TOwner>(attribute)
    {
        *this = attribute;
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    const ContainerAccessorsAttribute<TValue, TOwner>& ContainerAccessorsAttribute<TValue, TOwner>::operator=(const ContainerAccessorsAttribute& attribute)
    {
        if (this != &attribute)
        {
            AbstractAttributeT<TValue, TOwner>::operator=(attribute);
            _getter = attribute._getter;
            _setter = attribute._setter;
            _index = attribute._index;
        }
        return (*this);
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    ContainerAccessorsAttribute<TValue, TOwner>::~ContainerAccessorsAttribute()
    {
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    TValue ContainerAccessorsAttribute<TValue, TOwner>::getValue(const TOwner& owner) const
    {
        GLM_DEBUG_ASSERT(owner.getRTTI().isDerivedFrom(this->getOwnerRTTI()));
        return (owner.*_getter)(_index);
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    void ContainerAccessorsAttribute<TValue, TOwner>::setValue(TOwner& owner, TValue value) const
    {
        GLM_DEBUG_ASSERT(owner.getRTTI().isDerivedFrom(this->getOwnerRTTI()));
        (owner.*_setter)(_index, value);
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    void ContainerAccessorsAttribute<TValue, TOwner>::pack(BinaryStream& stream, const void* owner) const
    {
        stream.write(getValue(*static_cast<const TOwner*>(owner)));
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    void ContainerAccessorsAttribute<TValue, TOwner>::unpack(BinaryStream& stream, void* owner) const
    {
        TValue value(getValue(*static_cast<TOwner*>(owner)));
        stream.read(value);
        if (!stream.isFirstPass())
        {
            setValue(*static_cast<TOwner*>(owner), value);
        }
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    void ContainerAccessorsAttribute<TValue, TOwner>::pack(XMLStream& stream, DataItem& configurationItem, const void* owner) const
    {
        stream.write(configurationItem, getValue(*static_cast<const TOwner*>(owner)));
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    void ContainerAccessorsAttribute<TValue, TOwner>::unpack(XMLStream& stream, const DataItem& configurationItem, void* owner) const
    {
        TValue value(getValue(*static_cast<TOwner*>(owner)));
        stream.read(configurationItem, value);
        if (!stream.isFirstPass())
        {
            setValue(*static_cast<TOwner*>(owner), value);
        }
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    const RTTI& ContainerAccessorsAttribute<TValue, TOwner>::getAttributeRTTI() const
    {
        return RTTIAccessor<TValue>::getClassRTTI();
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    const RTTI& ContainerAccessorsAttribute<TValue, TOwner>::getAttributeClassRTTI()
    {
        return RTTIAccessor<TValue>::getClassRTTI();
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    void ContainerAccessorsAttribute<TValue, TOwner>::createAttributeRTTI()
    {
        RTTIAccessor<TValue>::createClassRTTI();
    }

    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    void ContainerAccessorsAttribute<TValue, TOwner>::destroyAttributeRTTI()
    {
        RTTIAccessor<TValue>::destroyClassRTTI();
    }

    //-------------------------------------------------------------------------
    // partial specialization ContainerAccessorsAttribute<TValue&>
    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    class ContainerAccessorsAttribute<TValue&, TOwner> : public AbstractAttributeT<TValue&, TOwner>
    {
        GLM_VIRTUAL_RTTI_T0_T1("20ceafbe-7b14-416f-8045-1456eec469c7", glm::ContainerAccessorsAttribute, TValue&, TOwner, addBaseClasses)

    public:
        typedef TValue& (TOwner::*Getter)(unsigned int index);
        typedef void (TOwner::*Setter)(unsigned int index, TValue& value);

        typedef TValue value_type;

        ContainerAccessorsAttribute(const char* name, TValue& (TOwner::*getter)(unsigned int index), void (TOwner::*setter)(unsigned int index, TValue& value), unsigned int index)
            : AbstractAttributeT<TValue&, TOwner>(name, &TOwner::getClassRTTI())
            , _getter(static_cast<Getter>(getter))
            , _setter(static_cast<Setter>(setter))
            , _index(index)
        {
            GLM_DEBUG_ASSERT((_getter != NULL) && (_setter != NULL));
            this->_attributeType = AbstractAttribute::AttributeType::REFERENCE;
        }

        virtual ~ContainerAccessorsAttribute()
        {
        }

        ContainerAccessorsAttribute(const ContainerAccessorsAttribute& attribute)
            : AbstractAttributeT<TValue&, TOwner>(attribute)
        {
            *this = attribute;
        }

        const ContainerAccessorsAttribute& operator=(const ContainerAccessorsAttribute& attribute)
        {
            if (this != &attribute)
            {
                AbstractAttributeT<TValue&, TOwner>::operator=(attribute);
                _getter = attribute._getter;
                _setter = attribute._setter;
                _index = attribute._index;
            }
            return (*this);
        }

        TValue& getReference(const TOwner& owner) const
        {
            GLM_DEBUG_ASSERT(owner.getRTTI().isDerivedFrom(this->getOwnerRTTI()));
            return (const_cast<TOwner&>(owner).*_getter)(_index);
        }

        void setReference(TOwner& owner, TValue& value) const
        {
            GLM_DEBUG_ASSERT(owner.getRTTI().isDerivedFrom(this->getOwnerRTTI()));
            (owner.*_setter)(_index, value);
        }

        const RTTI& getAttributeRTTI() const
        {
            return RTTIAccessor<TValue&>::getClassRTTI();
        }

        static const RTTI& getAttributeClassRTTI()
        {
            return RTTIAccessor<TValue&>::getClassRTTI();
        }

        static void createAttributeRTTI()
        {
            RTTIAccessor<TValue&>::createClassRTTI();
        }

        static void destroyAttributeRTTI()
        {
            RTTIAccessor<TValue&>::destroyClassRTTI();
        }

    private:
        void pack(BinaryStream& stream, const void* owner) const
        {
            stream.write(getReference(*static_cast<const TOwner*>(owner)));
        }

        void unpack(BinaryStream& stream, void* owner) const
        {
            TValue& value(getReference(*static_cast<TOwner*>(owner)));
            stream.read(value);
            if (!stream.isFirstPass())
            {
                setReference(*static_cast<TOwner*>(owner), value);
            }
        }

        void pack(XMLStream& stream, DataItem& configurationItem, const void* owner) const
        {
            stream.write(configurationItem, getReference(*static_cast<const TOwner*>(owner)));
        }

        void unpack(XMLStream& stream, const DataItem& configurationItem, void* owner) const
        {
            TValue& value(getReference(*static_cast<TOwner*>(owner)));
            stream.read(configurationItem, value);
            if (!stream.isFirstPass())
            {
                setReference(*static_cast<TOwner*>(owner), value);
            }
        }

        static void addBaseClasses()
        {
            ContainerAccessorsAttribute<const TValue&, TOwner>::getClassRTTI().template addBaseClass<AbstractAttributeT<TValue&, TOwner>>();
        }
        ContainerAccessorsAttribute()
        {
        }

        Getter _getter;
        Setter _setter;
        unsigned int _index;
    };

    template <class TValue, class TOwner>
    RTTI* ContainerAccessorsAttribute<TValue&, TOwner>::_rtti(NULL);

    //-------------------------------------------------------------------------
    // partial specialization ContainerAccessorsAttribute<const TValue&>
    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    class ContainerAccessorsAttribute<const TValue&, TOwner> : public AbstractAttributeT<const TValue&, TOwner>
    {
        GLM_VIRTUAL_RTTI_T0_T1("27d3c415-3639-4673-bb00-fdf716b0b871", glm::ContainerAccessorsAttribute, const TValue&, TOwner, addBaseClasses)

    public:
		GLM_CLASS_STAT_ID(glm::MemoryStatIds::GolaemShared)

        typedef const TValue& (TOwner::*Getter)(unsigned int index) const;
        typedef void (TOwner::*Setter)(unsigned int index, const TValue& value);

        typedef TValue value_type;

        ContainerAccessorsAttribute(const char* name, const TValue& (TOwner::*getter)(unsigned int index) const, void (TOwner::*setter)(unsigned int index, const TValue& value), unsigned int index)
            : AbstractAttributeT<const TValue&, TOwner>(name, &TOwner::getClassRTTI())
            , _getter(static_cast<Getter>(getter))
            , _setter(static_cast<Setter>(setter))
            , _index(index)
        {
            GLM_DEBUG_ASSERT((_getter != NULL) && (_setter != NULL));
            this->_attributeType = AbstractAttribute::AttributeType::CONST_REFERENCE;
        }

        virtual ~ContainerAccessorsAttribute()
        {
        }

        ContainerAccessorsAttribute(const ContainerAccessorsAttribute& attribute)
            : AbstractAttributeT<const TValue&, TOwner>(attribute)
        {
            *this = attribute;
        }

        const ContainerAccessorsAttribute& operator=(const ContainerAccessorsAttribute& attribute)
        {
            if (this != &attribute)
            {
                AbstractAttributeT<const TValue&, TOwner>::operator=(attribute);
                _getter = attribute._getter;
                _setter = attribute._setter;
                _index = attribute._index;
            }
            return (*this);
        }

        virtual const TValue& getConstReference(const TOwner& owner) const
        {
            GLM_DEBUG_ASSERT(owner.getRTTI().isDerivedFrom(this->getOwnerRTTI()));
            return (owner.*_getter)(_index);
        }

        virtual void setConstReference(TOwner& owner, const TValue& value) const
        {
            GLM_DEBUG_ASSERT(owner.getRTTI().isDerivedFrom(this->getOwnerRTTI()));
            (owner.*_setter)(_index, value);
        }

        const RTTI& getAttributeRTTI() const
        {
            return RTTIAccessor<const TValue&>::getClassRTTI();
        }

        static const RTTI& getAttributeClassRTTI()
        {
            return RTTIAccessor<const TValue&>::getClassRTTI();
        }

        static void createAttributeRTTI()
        {
            RTTIAccessor<const TValue&>::createClassRTTI();
        }

        static void destroyAttributeRTTI()
        {
            RTTIAccessor<const TValue&>::destroyClassRTTI();
        }

    private:
        virtual void setReference(TOwner& owner, TValue& value) const
        {
            setConstReference(owner, value);
        }

        void pack(BinaryStream& stream, const void* owner) const
        {
            stream.write(getConstReference(*static_cast<const TOwner*>(owner)));
        }

        void unpack(BinaryStream& stream, void* owner) const
        {
            if (stream.isFirstPass())
            {
                TValue* value = GLM_NEW( TValue, value,  MemoryStatIds::GolaemShared);
                stream.pushValueInFifo(static_cast<void*>(value));
                stream.read(*value);
            }
            else
            {
                TValue* value = (TValue*)(stream.popValuefromFifo());
                stream.read(*value);
                setConstReference(*static_cast<TOwner*>(owner), *value);
                GLM_DELETE(value,  MemoryStatIds::GolaemShared);
            }
        }

        void pack(XMLStream& stream, DataItem& configurationItem, const void* owner) const
        {
            stream.write(configurationItem, getConstReference(*static_cast<const TOwner*>(owner)));
        }

        void unpack(XMLStream& stream, const DataItem& configurationItem, void* owner) const
        {
            if (stream.isFirstPass())
            {
                TValue* value = new TValue();
                stream.pushValueInFifo(static_cast<void*>(value));
                stream.read(configurationItem, *value);
            }
            else
            {
                TValue* value = (TValue*)(stream.popValuefromFifo());
                stream.read(configurationItem, *value);

                setConstReference(*static_cast<TOwner*>(owner), *value);

                GLM_SAFE_DELETE(value);
            }
        }

        static void addBaseClasses()
        {
            ContainerAccessorsAttribute<const TValue&, TOwner>::getClassRTTI().template addBaseClass<AbstractAttributeT<const TValue&, TOwner>>();
        }
        ContainerAccessorsAttribute()
        {
        }

        Getter _getter;
        Setter _setter;
        unsigned int _index;
    };

    template <class TValue, class TOwner>
    RTTI* ContainerAccessorsAttribute<const TValue&, TOwner>::_rtti(NULL);

    //-------------------------------------------------------------------------
    // partial specialization ContainerAccessorsAttribute<TValue*>
    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    class ContainerAccessorsAttribute<TValue*, TOwner> : public AbstractAttributeT<TValue*, TOwner>
    {
        GLM_VIRTUAL_RTTI_T0_T1("87b3c0fd-10de-4e56-8094-fb66c1fa6776", glm::ContainerAccessorsAttribute, TValue*, TOwner, addBaseClasses)

    public:
        typedef TValue* (TOwner::*Getter)(unsigned int index) const;
        typedef void (TOwner::*Setter)(unsigned int index, TValue* value);

        typedef TValue value_type;

        ContainerAccessorsAttribute(const char* name, TValue* (TOwner::*getter)(unsigned int index) const, void (TOwner::*setter)(unsigned int index, TValue* value), unsigned int index)
            : AbstractAttributeT<TValue*, TOwner>(name, &TOwner::getClassRTTI())
            , _getter(static_cast<Getter>(getter))
            , _setter(static_cast<Setter>(setter))
            , _index(index)
        {
            GLM_DEBUG_ASSERT((_getter != NULL) && (_setter != NULL));
            this->_attributeType = AbstractAttribute::AttributeType::POINTER;
        }

        virtual ~ContainerAccessorsAttribute()
        {
        }

        ContainerAccessorsAttribute(const ContainerAccessorsAttribute& attribute)
            : AbstractAttributeT<TValue*, TOwner>(attribute)
        {
            *this = attribute;
        }

        const ContainerAccessorsAttribute& operator=(const ContainerAccessorsAttribute& attribute)
        {
            if (this != &attribute)
            {
                AbstractAttributeT<TValue*, TOwner>::operator=(attribute);
                _getter = attribute._getter;
                _setter = attribute._setter;
                _index = attribute._index;
            }
            return (*this);
        }

        TValue* getPointer(const TOwner* owner) const
        {
            GLM_DEBUG_ASSERT(owner->getRTTI().isDerivedFrom(this->getOwnerRTTI()));
            return (owner->*_getter)(_index);
        }

        void setPointer(TOwner* owner, TValue* value) const
        {
            GLM_DEBUG_ASSERT(owner->getRTTI().isDerivedFrom(this->getOwnerRTTI()));
            (owner->*_setter)(_index, value);
        }

        const RTTI& getAttributeRTTI() const
        {
            return RTTIAccessor<TValue*>::getClassRTTI();
        }

        static const RTTI& getAttributeClassRTTI()
        {
            return RTTIAccessor<TValue*>::getClassRTTI();
        }

        static void createAttributeRTTI()
        {
            RTTIAccessor<TValue*>::createClassRTTI();
        }

        static void destroyAttributeRTTI()
        {
            RTTIAccessor<TValue*>::destroyClassRTTI();
        }

    private:
        void pack(BinaryStream& stream, const void* owner) const
        {
            stream.write(getPointer(static_cast<const TOwner*>(owner)));
        }

        void unpack(BinaryStream& stream, void* owner) const
        {
            TValue* value(NULL);
            stream.read(value);
            if (!stream.isFirstPass())
            {
                setPointer(static_cast<TOwner*>(owner), value);
            }
        }

        void pack(XMLStream& stream, DataItem& configurationItem, const void* owner) const
        {
            stream.write(configurationItem, getPointer(static_cast<const TOwner*>(owner)));
        }

        void unpack(XMLStream& stream, const DataItem& configurationItem, void* owner) const
        {
            TValue* value(NULL);
            stream.read(configurationItem, value);
            if (!stream.isFirstPass())
            {
                setPointer(static_cast<TOwner*>(owner), value);
            }
        }

        static void addBaseClasses()
        {

            ContainerAccessorsAttribute<TValue*, TOwner>::getClassRTTI().template addBaseClass<AbstractAttributeT<TValue*, TOwner>>();
        }
        ContainerAccessorsAttribute()
        {
        }

        Getter _getter;
        Setter _setter;
        unsigned int _index;
    };

    template <class TValue, class TOwner>
    RTTI* ContainerAccessorsAttribute<TValue*, TOwner>::_rtti(NULL);

    //-------------------------------------------------------------------------
    // partial specialization ContainerAccessorsAttribute<const TValue*>
    //-------------------------------------------------------------------------
    template <class TValue, class TOwner>
    class ContainerAccessorsAttribute<const TValue*, TOwner> : public AbstractAttributeT<const TValue*, TOwner>
    {
        GLM_VIRTUAL_RTTI_T0_T1("e98077c4-25f0-420e-9b49-37bc005e8cd3", glm::ContainerAccessorsAttribute, const TValue*, TOwner, addBaseClasses)

    public:
        typedef const TValue* (TOwner::*Getter)(unsigned int index) const;
        typedef void (TOwner::*Setter)(unsigned int index, const TValue* value);

        typedef TValue value_type;

        ContainerAccessorsAttribute(const char* name, const TValue* (TOwner::*getter)(unsigned int index) const, void (TOwner::*setter)(unsigned int index, const TValue* value), unsigned int index)
            : AbstractAttributeT<const TValue*, TOwner>(name, &TOwner::getClassRTTI())
            , _getter(static_cast<Getter>(getter))
            , _setter(static_cast<Setter>(setter))
            , _index(index)
        {
            GLM_DEBUG_ASSERT((_getter != NULL) && (_setter != NULL));
            this->_attributeType = AbstractAttribute::AttributeType::CONST_POINTER;
        }

        virtual ~ContainerAccessorsAttribute()
        {
        }

        ContainerAccessorsAttribute(const ContainerAccessorsAttribute& attribute)
            : AbstractAttributeT<const TValue*, TOwner>(attribute)
        {
            *this = attribute;
        }

        const ContainerAccessorsAttribute& operator=(const ContainerAccessorsAttribute& attribute)
        {
            if (this != &attribute)
            {
                AbstractAttributeT<const TValue*, TOwner>::operator=(attribute);
                _getter = attribute._getter;
                _setter = attribute._setter;
                _index = attribute._index;
            }
            return (*this);
        }

        const TValue* getConstPointer(const TOwner& owner) const
        {
            GLM_DEBUG_ASSERT(owner.getRTTI().isDerivedFrom(this->getOwnerRTTI()));
            return (owner.*_getter)(_index);
        }

        void setConstPointer(TOwner& owner, const TValue* value) const
        {
            GLM_DEBUG_ASSERT(owner.getRTTI().isDerivedFrom(this->getOwnerRTTI()));
            (owner.*_setter)(_index, value);
        }

        const RTTI& getAttributeRTTI() const
        {
            return RTTIAccessor<const TValue*>::getClassRTTI();
        }

        static const RTTI& getAttributeClassRTTI()
        {
            return RTTIAccessor<const TValue*>::getClassRTTI();
        }

        static void createAttributeRTTI()
        {
            RTTIAccessor<const TValue*>::createClassRTTI();
        }

        static void destroyAttributeRTTI()
        {
            RTTIAccessor<const TValue*>::destroyClassRTTI();
        }

    private:
        void pack(BinaryStream& stream, const void* owner) const
        {
            stream.write(getConstPointer(*static_cast<const TOwner*>(owner)));
        }

        void unpack(BinaryStream& stream, void* owner) const
        {
            const TValue* value(NULL);
            stream.read(value);
            if (!stream.isFirstPass())
            {
                setConstPointer(*static_cast<TOwner*>(owner), value);
            }
        }

        void pack(XMLStream& stream, DataItem& configurationItem, const void* owner) const
        {
            stream.write(configurationItem, getConstPointer(*static_cast<const TOwner*>(owner)));
        }

        void unpack(XMLStream& stream, const DataItem& configurationItem, void* owner) const
        {
            const TValue* value(NULL);
            stream.read(configurationItem, value);
            if (!stream.isFirstPass())
            {
                setConstPointer(*static_cast<TOwner*>(owner), value);
            }
        }

        static void addBaseClasses()
        {

            ContainerAccessorsAttribute<const TValue*, TOwner>::getClassRTTI().template addBaseClass<AbstractAttributeT<const TValue*, TOwner>>();
        }
        ContainerAccessorsAttribute()
        {
        }

        Getter _getter;
        Setter _setter;
        unsigned int _index;
    };

    template <class TValue, class TOwner>
    RTTI* ContainerAccessorsAttribute<const TValue*, TOwner>::_rtti(NULL);
} // namespace glm
