TypeTraits.h
// TypeTraits.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2012
@import "cxObject.h"
@import "MacroUtils.h"
#include "Ceda/cxUtils/BasicTypes.h"
#include <type_traits>
/*
New proposal for type traits information provided by Xcpp 22 Sep 2022
---------------------------------------------------------
The existing approach is cumbersome, and involves a lot of generated code. For example the following might be created for
interface Ix
namespace ceda
{
template<> struct TypeTraits<Ix>
{
static const bool is_exported = 0;
static const bool is_reflected = 0;
static const bool is_registered = 0;
static const ceda::ETypeTraitKind kind = ceda::TTK_interface;
static const bool has_metadata = 0;
};
template<> struct InterfaceTypeTraits<Ix>
{
static const bool is_ipc = 0;
static const bool is_rmi = 0;
static const bool is_rpc = 0;
};
} // namespace ceda
We want to instead make use of bit flags because it's more efficient.
*/
namespace ceda
{
//////////// maps T to void or const void depending on whether T is const qualified //////////////
template < typename T >
struct to_void
{
typedef void type;
};
template < typename T >
struct to_void< const T >
{
typedef const void type;
};
enum class ETypeTraitBits
{
is_struct, // $struct
is_class, // $class
is_adt, // $adt
is_model, // $model
is_interface, // $interface
is_functor, // $functor
is_variant, // $variant
is_enum, // $enum
is_exported,
is_reflected,
is_registered,
has_metadata,
implements_IObject,
implements_IPersistable,
can_serialise_model,
has_model,
using_model_base_class,
is_ipc,
is_rmi,
is_rpc
};
constexpr bool TestBit(uint64 flags, ETypeTraitBits bit)
{
return (flags & ( ((uint64)1) << (uint64) bit)) != 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Common traits
/*
enum ETypeTraitKind
{
TTK_other, // None of the below
TTK_struct, // $struct
TTK_class, // $class
TTK_adt, // $adt
TTK_model, // $model
TTK_interface, // $interface
TTK_functor, // $functor
TTK_variant, // $variant
TTK_enum, // $enum
};
template< typename T >
struct TypeTraits
{
static const ETypeTraitKind kind = TTK_other;
static const bool is_exported = false;
static const bool is_reflected = false;
static const bool is_registered = false;
static const bool has_metadata = false;
};
template< typename T >
struct TypeTraits<const T> : public TypeTraits<T> {};
// Support the convention used by boost and C++11.
@for (i in [other,struct,class,adt,model,interface,functor,variant,enum])
{
template< typename T >
struct is_@@i
{
static const bool value = TypeTraits<T>::kind == TTK_@@i;
};
}
// Support the convention used by boost and C++11.
@for (i in [is_exported, is_registered, has_metadata])
{
template< typename T >
struct i
{
static const bool value = TypeTraits<T>::i;
};
}
*/
template< typename T >
struct TypeTraits
{
};
template< typename T >
struct TypeTraits<const T> : public TypeTraits<T> {};
@for (test in
[
is_struct,
is_class,
is_adt,
is_model,
is_interface,
is_functor,
is_variant,
is_enum,
is_exported,
//is_reflected,
is_registered,
has_metadata,
implements_IObject,
implements_IPersistable,
can_serialise_model,
has_model,
using_model_base_class,
is_ipc,
is_rmi,
is_rpc
])
{
template< typename T >
struct test
{
static const bool value = TestBit( TypeTraits<T>::flags, ETypeTraitBits::test );
};
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Classes
template< typename T >
struct ClassTypeTraits
{
};
template< typename T >
struct ClassTypeTraits<const T> : public ClassTypeTraits<T> {};
/*
template< typename T >
struct ClassTypeTraits
{
static const bool implements_IObject = false;
static const bool implements_IPersistable = false;
static const bool can_serialise_model = false;
static const bool has_model = false;
static const bool using_model_base_class = false;
};
template< typename T >
struct ClassTypeTraits<const T> : public ClassTypeTraits<T> {};
// Support the convention used by boost and C++11.
@for (i in
[
implements_IObject,
implements_IPersistable,
can_serialise_model,
has_model,
using_model_base_class
])
{
template< typename T >
struct i
{
static const bool value = ClassTypeTraits<T>::i;
};
}
*/
// C directly implements interface I
template< typename C, typename I >
struct directly_implements_interface
{
static const bool value = false;
};
// C indirectly implements interface I
template< typename C, typename I >
struct indirectly_implements_interface
{
static const bool value = false;
};
template< typename C, typename I >
struct implements_interface
{
static const bool value = directly_implements_interface<C,I>::value ||
indirectly_implements_interface<C,I>::value;
};
///////////////////////////////////////////////////////////////////////////////////////////////
// Interfaces
/*
template< typename T >
struct InterfaceTypeTraits
{
static const bool is_ipc = false;
static const bool is_rmi = false;
};
template< typename T >
struct InterfaceTypeTraits<const T> : public InterfaceTypeTraits<T> {};
// Support the convention used by boost and C++11.
@for (i in
[
is_ipc,
is_rmi
])
{
template< typename T >
struct i
{
static const bool value = InterfaceTypeTraits<T>::i;
};
}
*/
// T1 is a direct superinterface of T2
template< typename T1, typename T2 >
struct _is_direct_superinterface_of
{
static const bool value = false;
};
// T1 is an indirect superinterface of T2
template< typename T1, typename T2 >
struct _is_indirect_superinterface_of
{
static const bool value = false;
};
/*
bool is_direct_superinterface_of<T1,T2>::value
bool is_indirect_superinterface_of<T1,T2>::value
bool is_proper_superinterface_of<T1,T2>::value
bool is_superinterface_of<T1,T2>::value
The direct and indirect superinterfaces of a given interface are mutually exclusive. Their
union gives the set of proper superinterfaces. Taking the reflexive closure gives the
superinterfaces (every interface is a superinterface of itself).
is_superinterface_of<I1,I2> handles const qualification correctly. E.g.
a. is_superinterface_of<IObject,IPersistable>::value = true
b. is_superinterface_of<const IObject,IPersistable>::value = true
c. is_superinterface_of<IObject,const IPersistable>::value = false
d. is_superinterface_of<const IObject,const IPersistable>::value = true
*/
////////////////// is_direct_superinterface_of
// account for const qualification
template< typename T1, typename T2 >
struct is_direct_superinterface_of
{
static const bool value = _is_direct_superinterface_of<T1,T2>::value;
};
template< typename T1, typename T2 >
struct is_direct_superinterface_of<T1,const T2>
{
static const bool value = false;
};
template< typename T1, typename T2 >
struct is_direct_superinterface_of<const T1,T2>
{
static const bool value = _is_direct_superinterface_of<T1,T2>::value;
};
template< typename T1, typename T2 >
struct is_direct_superinterface_of<const T1, const T2>
{
static const bool value = _is_direct_superinterface_of<T1,T2>::value;
};
////////////////// is_indirect_superinterface_of
// account for const qualification
template< typename T1, typename T2 >
struct is_indirect_superinterface_of
{
static const bool value = _is_indirect_superinterface_of<T1,T2>::value;
};
template< typename T1, typename T2 >
struct is_indirect_superinterface_of<T1,const T2>
{
static const bool value = false;
};
template< typename T1, typename T2 >
struct is_indirect_superinterface_of<const T1,T2>
{
static const bool value = _is_indirect_superinterface_of<T1,T2>::value;
};
template< typename T1, typename T2 >
struct is_indirect_superinterface_of<const T1, const T2>
{
static const bool value = _is_indirect_superinterface_of<T1,T2>::value;
};
////////////////// is_same_supertype_of
// account for const qualification
template< typename T1, typename T2 >
struct is_same_supertype_of
{
static const bool value = std::is_same<T1,T2>::value;
};
template< typename T1, typename T2 >
struct is_same_supertype_of<T1,const T2>
{
static const bool value = false;
};
template< typename T1, typename T2 >
struct is_same_supertype_of<const T1,T2>
{
static const bool value = std::is_same<T1,T2>::value;
};
template< typename T1, typename T2 >
struct is_same_supertype_of<const T1, const T2>
{
static const bool value = std::is_same<T1,T2>::value;
};
//////////////////
template< typename T1, typename T2 >
struct is_proper_superinterface_of
{
static const bool value = is_direct_superinterface_of<T1,T2>::value ||
is_indirect_superinterface_of<T1,T2>::value;
};
template< typename T1, typename T2 >
struct is_superinterface_of
{
static const bool value = is_same_supertype_of<T1,T2>::value ||
is_proper_superinterface_of<T1,T2>::value;
};
} // namespace ceda