]> git.tdb.fi Git - libs/core.git/commitdiff
Exactly-sized integer types, the C++ way
authorMikko Rasa <tdb@tdb.fi>
Wed, 1 Aug 2012 13:57:37 +0000 (16:57 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 1 Aug 2012 14:14:09 +0000 (17:14 +0300)
source/core/inttypes.h [new file with mode: 0644]
source/core/typelist.h [new file with mode: 0644]

diff --git a/source/core/inttypes.h b/source/core/inttypes.h
new file mode 100644 (file)
index 0000000..3bdac35
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef MSP_CORE_INTTYPES_H_
+#define MSP_CORE_INTTYPES_H_
+
+#include <climits>
+#include "typelist.h"
+
+namespace Msp {
+
+// Define lists of standard types, both signed and unsigned variants
+typedef TypeList<signed char, short, int, long>::Type StandardSignedTypes;
+typedef TypeList<unsigned char, unsigned short, unsigned int, unsigned long>::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<StandardSignedTypes, long long, __int128>::Type PlatformSignedTypes;
+typedef TypeList<StandardUnsignedTypes, unsigned long long, unsigned __int128>::Type PlatformUnsignedTypes;
+#pragma GCC diagnostic pop
+#else
+typedef TypeList<StandardSignedTypes, long long>::Type PlatformSignedTypes;
+typedef TypeList<StandardUnsignedTypes, unsigned long long>::Type PlatformUnsignedTypes;
+#endif
+#elif defined(_MSC_VER)
+typedef TypeList<StandardSignedTypes, __int64>::Type PlatformSignedTypes;
+typedef TypeList<StandardUnsignedTypes, unsigned __int64>::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<unsigned size>
+struct Int
+{
+       template<typename T>
+       struct Predicate
+       {
+               enum { value = (sizeof(T)*CHAR_BIT==size) };
+       };
+
+       typedef typename TypeChooser<PlatformSignedTypes, Predicate>::Type SignedType;
+       typedef typename TypeChooser<PlatformUnsignedTypes, Predicate>::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 (file)
index 0000000..bd8bf44
--- /dev/null
@@ -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<typename H, typename T>
+struct TypeCons
+{
+       typedef H Head;
+       typedef T Tail;
+};
+
+
+/** Basic terminated type list of one element. */
+template<typename T1>
+struct TypeList1
+{
+       typedef TypeCons<T1, NullType> Type;
+};
+
+/** Specialization to avoid creating a TypeCons with two NullTypes. */
+template<>
+struct TypeList1<NullType>
+{
+       typedef NullType Type;
+};
+
+/** Specialization to avoid creating a TypeCons with another TypeCons as its
+head. */
+template<typename T1, typename T2>
+struct TypeList1<TypeCons<T1, T2> >
+{
+       typedef TypeCons<T1, T2> Type;
+};
+
+/** Basic terminated type list of two elements. */
+template<typename T1, typename T2>
+struct TypeList2
+{
+       typedef TypeCons<T1, typename TypeList1<T2>::Type> Type;
+};
+
+/** Specialization to ignore an initial NullType. */
+template<typename T1>
+struct TypeList2<NullType, T1>
+{
+       typedef typename TypeList1<T1>::Type Type;
+};
+
+/** Specialization to flatten an initial TypeCons. */
+template<typename T1, typename T2, typename T3>
+struct TypeList2<TypeCons<T1, T2>, T3>
+{
+       typedef typename TypeList2<T1, typename TypeList2<T2, T3>::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<typename T1, typename T2 = NullType, typename T3 = NullType, typename T4 = NullType, typename T5 = NullType>
+struct TypeList
+{
+       typedef typename TypeList<T1, typename TypeList<T2, T3, T4, T5>::Type>::Type Type;
+};
+
+/** Specialization of TypeList for one element. */
+template<typename T1>
+struct TypeList<T1, NullType, NullType, NullType, NullType>
+{
+       typedef typename TypeList1<T1>::Type Type;
+};
+
+/** Specialization of TypeList for two elements. */
+template<typename T1, typename T2>
+struct TypeList<T1, T2, NullType, NullType, NullType>
+{
+       typedef typename TypeList2<T1, T2>::Type Type;
+};
+
+/** Specialization of TypeList for three elements. */
+template<typename T1, typename T2, typename T3>
+struct TypeList<T1, T2, T3, NullType, NullType>
+{
+       typedef typename TypeList<T1, typename TypeList<T2, T3>::Type>::Type Type;
+};
+
+/** Specialization of TypeList for four elements. */
+template<typename T1, typename T2, typename T3, typename T4>
+struct TypeList<T1, T2, T3, T4, NullType>
+{
+       typedef typename TypeList<T1, typename TypeList<T2, T3, T4>::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<typename L, template<typename> class P, bool f = P<typename L::Head>::value>
+struct TypeChooser;
+
+/** Specialization for a matching type.  Picks the head of the list as the
+result. */
+template<typename L, template<typename> class P>
+struct TypeChooser<L, P, true>
+{
+       typedef typename L::Head Type;
+};
+
+/** Specialization for a non-matchin type.  Recursively inspects the tail of
+the list. */
+template<typename L, template<typename> class P>
+struct TypeChooser<L, P, false>
+{
+       typedef typename TypeChooser<typename L::Tail, P>::Type Type;
+};
+
+} // namespace Msp
+
+#endif