ReflectedQualifier.h

// ReflectedQualifier.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2022

@import "IObject.h"
@import "ReflectedType.h"

namespace ceda
{
// ReflectedQualifier for T*, ptr<T>, pref<T>, cref<T>, openvariant<T>

struct ReflectedQualifier
{
    const TypeOps& ops;
    ReflectedType element;
};

@api xostream& operator<<(xostream& os, const ReflectedQualifier& r);

// Q is the qualfied type, E is the element type
template<typename Q, typename E>
inline const ReflectedQualifier& GetReflectedQualifier()
{
    static ReflectedQualifier s =
    {
        GetTypeOpsX<Q>()
    };
    static bool init = false;
    if (!init)
    {
        init = true;
        s.element = GetReflectedType<E>();
    }
    return s;
}

/*
template<typename T>
inline const ReflectedPointer& GetReflectedPointer() { return GetReflectedQualifier<void*,T>(); }

template<typename T>
inline const ReflectedInterfacePtr& GetReflectedInterfacePtr() { return GetReflectedQualifier<AnyInterface,T>(); }

template<typename T>
inline const ReflectedPref& GetReflectedPref() { return GetReflectedQualifier<PseudoPref,T>(); }

template<typename T>
inline const ReflectedOpenVariant& GetReflectedOpenVariant() { return GetReflectedQualifier<AnyInterface,T>(); }
*/

template<typename T>
inline const ReflectedPointer& GetReflectedPointer() { return GetReflectedQualifier<T*,T>(); }

template<typename T>
inline const ReflectedInterfacePtr& GetReflectedInterfacePtr() { return GetReflectedQualifier<AnyInterface,T>(); }
//inline const ReflectedInterfacePtr& GetReflectedInterfacePtr() { return GetReflectedQualifier<ptr<T>,T>(); }

template<typename T>
inline const ReflectedPref& GetReflectedPref() { return GetReflectedQualifier<pref<T>,T>(); }

template<typename T>
inline const ReflectedCref& GetReflectedCref() { return GetReflectedQualifier<cref<T>,T>(); }

template<typename T>
inline const ReflectedOpenVariant& GetReflectedOpenVariant() { return GetReflectedQualifier<openvariant<T>,T>(); }

template<typename T> struct is_ptr { constexpr static bool value = false; };
template<typename I> struct is_ptr<ptr<I>> { constexpr static bool value = true; };
template<typename I> struct is_ptr<ptr<const I>> { constexpr static bool value = true; };

template<typename T> struct is_pref { constexpr static bool value = false; };
template<typename I> struct is_pref<pref<I>> { constexpr static bool value = true; };
template<typename I> struct is_pref<pref<const I>> { constexpr static bool value = true; };

template<typename T> struct is_cref { constexpr static bool value = false; };
template<typename T> struct is_cref<cref<T>> { constexpr static bool value = true; };
template<typename T> struct is_cref<cref<const T>> { constexpr static bool value = true; };

template<typename T> struct is_OpenVariant { constexpr static bool value = false; };
template<typename I> struct is_OpenVariant<openvariant<I>> { constexpr static bool value = true; };

template<typename K>
struct GetReflectedType_class<K*> 
{
    static inline ReflectedType get()
    {
        ReflectedType r;
        r.tag = EReflectedTypeTag::Pointer;
        r.Pointer = &GetReflectedPointer<K>();
        return r;
    }
};

template<typename I>
struct GetReflectedType_class<ptr<I>> 
{
    static inline ReflectedType get()
    {
        ReflectedType r;
        r.tag = EReflectedTypeTag::InterfacePtr;
        r.InterfacePtr = &GetReflectedInterfacePtr<I>();
        return r;
    }
};

template<typename I>
struct GetReflectedType_class<pref<I>> 
{
    static inline ReflectedType get()
    {
        ReflectedType r;
        r.tag = EReflectedTypeTag::Pref;
        r.Pref = &GetReflectedPref<I>();
        return r;
    }
};

template<typename T>
struct GetReflectedType_class<cref<T>> 
{
    static inline ReflectedType get()
    {
        ReflectedType r;
        r.tag = EReflectedTypeTag::Cref;
        r.Cref = &GetReflectedCref<T>();
        return r;
    }
};

template<typename I>
struct GetReflectedType_class<openvariant<I>> 
{
    static inline ReflectedType get()
    {
        ReflectedType r;
        r.tag = EReflectedTypeTag::OpenVariant;
        r.OpenVariant = &GetReflectedOpenVariant<I>();
        return r;
    }
};
} // namespace ceda