From 4bd704ea84b36dc8e83db51cd5eab4111eb48c2a Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 1 Aug 2012 16:57:37 +0300 Subject: [PATCH] Exactly-sized integer types, the C++ way --- source/core/inttypes.h | 61 +++++++++++++++++++ source/core/typelist.h | 130 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 source/core/inttypes.h create mode 100644 source/core/typelist.h diff --git a/source/core/inttypes.h b/source/core/inttypes.h new file mode 100644 index 0000000..3bdac35 --- /dev/null +++ b/source/core/inttypes.h @@ -0,0 +1,61 @@ +#ifndef MSP_CORE_INTTYPES_H_ +#define MSP_CORE_INTTYPES_H_ + +#include +#include "typelist.h" + +namespace Msp { + +// Define lists of standard types, both signed and unsigned variants +typedef TypeList::Type StandardSignedTypes; +typedef TypeList::Type StandardUnsignedTypes; + +// Then add possible nonstandard types +#if defined(__GNUC__) +#if (__GNUC__>4 || (__GNUC__==4 && __GNUC_MINOR__>=6)) && defined(__LP64__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-pedantic" +typedef TypeList::Type PlatformSignedTypes; +typedef TypeList::Type PlatformUnsignedTypes; +#pragma GCC diagnostic pop +#else +typedef TypeList::Type PlatformSignedTypes; +typedef TypeList::Type PlatformUnsignedTypes; +#endif +#elif defined(_MSC_VER) +typedef TypeList::Type PlatformSignedTypes; +typedef TypeList::Type PlatformUnsignedTypes; +#else +typedef StandardSignedTypes PlatformSignedTypes; +typedef StandardUnsignedTypes PlatformUnsignedTypes; +#endif + +/** A helper for choosing an integer type of a specific size. The size +parameter is in bits. The resulting types can be obtained from the SignedType +and UnsignedType typedefs. */ +template +struct Int +{ + template + struct Predicate + { + enum { value = (sizeof(T)*CHAR_BIT==size) }; + }; + + typedef typename TypeChooser::Type SignedType; + typedef typename TypeChooser::Type UnsignedType; +}; + +// Finally define convenient shorthands for the actual integer types +typedef Int<8>::SignedType Int8; +typedef Int<8>::UnsignedType UInt8; +typedef Int<16>::SignedType Int16; +typedef Int<16>::UnsignedType UInt16; +typedef Int<32>::SignedType Int32; +typedef Int<32>::UnsignedType UInt32; +typedef Int<64>::SignedType Int64; +typedef Int<64>::UnsignedType UInt64; + +} // namespace Msp + +#endif diff --git a/source/core/typelist.h b/source/core/typelist.h new file mode 100644 index 0000000..bd8bf44 --- /dev/null +++ b/source/core/typelist.h @@ -0,0 +1,130 @@ +#ifndef CORE_TYPELIST_H_ +#define CORE_TYPELIST_H_ + +namespace Msp { + +/** Sentinel type for type lists */ +struct NullType { }; + + +/** A "cons cell" for types. Composed of a head and a tail. To construct +longer lists, use another TypeCons as the tail. The tail of the last TypeCons +should by NullType. */ +template +struct TypeCons +{ + typedef H Head; + typedef T Tail; +}; + + +/** Basic terminated type list of one element. */ +template +struct TypeList1 +{ + typedef TypeCons Type; +}; + +/** Specialization to avoid creating a TypeCons with two NullTypes. */ +template<> +struct TypeList1 +{ + typedef NullType Type; +}; + +/** Specialization to avoid creating a TypeCons with another TypeCons as its +head. */ +template +struct TypeList1 > +{ + typedef TypeCons Type; +}; + +/** Basic terminated type list of two elements. */ +template +struct TypeList2 +{ + typedef TypeCons::Type> Type; +}; + +/** Specialization to ignore an initial NullType. */ +template +struct TypeList2 +{ + typedef typename TypeList1::Type Type; +}; + +/** Specialization to flatten an initial TypeCons. */ +template +struct TypeList2, T3> +{ + typedef typename TypeList2::Type>::Type Type; +}; + + +/** A terminated type list of five elements. Use the typedef Type inside to +obtain the actual list type. If any of the types is a type list itself, the +entire structure is flattened to a single list. */ +template +struct TypeList +{ + typedef typename TypeList::Type>::Type Type; +}; + +/** Specialization of TypeList for one element. */ +template +struct TypeList +{ + typedef typename TypeList1::Type Type; +}; + +/** Specialization of TypeList for two elements. */ +template +struct TypeList +{ + typedef typename TypeList2::Type Type; +}; + +/** Specialization of TypeList for three elements. */ +template +struct TypeList +{ + typedef typename TypeList::Type>::Type Type; +}; + +/** Specialization of TypeList for four elements. */ +template +struct TypeList +{ + typedef typename TypeList::Type>::Type Type; +}; + + +/** A helper for selecting a type from a list based on a predicate. The +predicate should be a template taking a single type argument and defining a +compile-time constant with the name "value", which evaluates to true if the +type is considered a match. The result can be obtained from the member +typedef Type. If the list contains no matching type, an ugly and confusing +compiler error will result. */ +template class P, bool f = P::value> +struct TypeChooser; + +/** Specialization for a matching type. Picks the head of the list as the +result. */ +template class P> +struct TypeChooser +{ + typedef typename L::Head Type; +}; + +/** Specialization for a non-matchin type. Recursively inspects the tail of +the list. */ +template class P> +struct TypeChooser +{ + typedef typename TypeChooser::Type Type; +}; + +} // namespace Msp + +#endif -- 2.43.0