/***************************************************************************** * $LastChangedDate: 2009-12-18 16:29:35 -0500 (Fri, 18 Dec 2009) $ * @file * @author Jim E. Brooks http://www.palomino3d.org * @brief Basic types. *//* * LEGAL: COPYRIGHT (C) 2004 JIM E. BROOKS * THIS SOURCE CODE IS RELEASED UNDER THE TERMS * OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2). *****************************************************************************/ #ifndef BASE_TYPES_HH #define BASE_TYPES_HH 1 // Basic types must be fast, prevent them having virtual functions. #define virtual VIRTUAL_METHODS_IN_BASIC_TYPES_IS_TOO_SLOW //////////////////////////////////////////////////////////////////////////////// // Basic types. // #if ! BASE_OMIT_BOOL typedef unsigned char Bool; ///< byte-sized bool #endif typedef unsigned char uchar; #ifdef OS_WINDOWS #undef uint #define uint unsigned int #else typedef unsigned int uint; #endif #undef ulong typedef unsigned long ulong; typedef float fp; #if SPEED typedef fp fpx; // extended-precision float #else typedef double fpx; #endif #define UINT_CAST( U ) (static_cast((U))) #define ULONG_CAST( U ) (static_cast((U))) //------------------------------------------------------------------------------ namespace base { //////////////////////////////////////////////////////////////////////////////// // Exact-size types (limited use). // int64() cast or "LL" suffix is critical to compile 64-bit shifts correctly. #if ! NO_STDINT typedef int8_t int8; typedef uint8_t uint8; typedef int16_t int16; typedef uint16_t uint16; typedef int32_t int32; typedef uint32_t uint32; typedef int64_t int64; // C99 typedef uint64_t uint64; // C99 #else typedef char int8; typedef unsigned char uint8; typedef short int16; typedef unsigned short uint16; typedef int int32; typedef unsigned int uint32; typedef long long int64; // C99 typedef unsigned long long uint64; // C99 #endif //////////////////////////////////////////////////////////////////////////////// // Limited use: may result in unportable code. // FYI, on Linux x86-64, int is 32-bits, long is 64-bits. // const uint INT_BITS = sizeof(int) * 8; const uint LONG_BITS = sizeof(long) * 8; const uint POINTER_BITS = sizeof(void*) * 8; /// @class base::Void /// @brief Void that can be instantiated (useful with templates). class Void { }; //////////////////////////////////////////////////////////////////////////////// /// @brief Macro to turn a fundamental type into a distinct class. /// @verbatim /// For example: /// DECLARE_DISTINCT_TYPE( Radian, fp ) /// DECLARE_DISTINCT_TYPE( Degree, fp ) /// BTW, this can't done using a template class and typedefs /// as the typedefs would still be the same type eg: /// typedef Distinct Radian; /// typedef Distinct Degree; /// @endverbatim /// /// ---------------------------------------------------------------------------- /// NOTE: DECLARE_DISTINCT_TYPE() MIGHT CAUSE BUGS IF NOT CAREFUL! /// !!!!! DECLARE_DISTINCT_TYPE() allows implied conversion to fundamental type! /// Instead use DECLARE_DISTINCT_TYPE_STRICT() to force explicit conversion. /// ---------------------------------------------------------------------------- #define DECLARE_DISTINCT_TYPE( CLASS, T, CONV_FUNC ) \ class CLASS \ { \ public: \ typedef T value_type; \ CLASS( void ) : mVal(0) { } /* clients depends on zero */ \ CLASS( T val ) : mVal(val) { } \ T CONV_FUNC( void ) const { return mVal; } /* explicit conversion */ \ operator T() const { return mVal; } \ CLASS& operator=( const T& val ) { mVal = val; return *this; } \ friend bool operator==( const CLASS a, const CLASS b ) { return a.mVal == b.mVal; } \ friend bool operator!=( const CLASS a, const CLASS b ) { return a.mVal != b.mVal; } \ /* Arithmetic operators are omitted because of ambiguity. */ \ /* Rather, cast to fundamental type then do the math. */ \ private: \ T mVal; \ }; // Strict variant requires explicit conversion. // This one is tedious but it can prevent conversion bugs. // Example: // DECLARE_DISTINCT_TYPE_STRICT( Meter, fp, FP ) // void Func( Meter meter ) // { // fp distance = ...; // fp sum = distance + meter.FP(); // explicitly convert to fp // } #define DECLARE_DISTINCT_TYPE_STRICT( CLASS, T, CONV_FUNC ) \ class CLASS \ { \ public: \ typedef T value_type; \ CLASS( void ) : mVal(0) { } /* clients depends on zero */ \ explicit CLASS( T val ) : mVal(val) { } /* explicit conversion */ \ /* operator T() const { return mVal; } [wrong] */ \ T CONV_FUNC( void ) const { return mVal; } /* explicit conversion */ \ /*CLASS& operator=( const T& val ) { mVal = val; return *this; } [circumvents] */ \ CLASS& operator=( const CLASS src ) { mVal = src.mVal; return *this; } \ CLASS& operator+=( const CLASS src ) { mVal += src.mVal; return *this; } \ CLASS& operator-=( const CLASS src ) { mVal -= src.mVal; return *this; } \ CLASS& operator*=( const CLASS src ) { mVal *= src.mVal; return *this; } \ CLASS& operator/=( const CLASS src ) { mVal /= src.mVal; return *this; } \ friend CLASS operator+( CLASS a, CLASS b ) { return CLASS(a.mVal + b.mVal); } \ friend CLASS operator-( CLASS a, CLASS b ) { return CLASS(a.mVal - b.mVal); } \ friend CLASS operator*( CLASS a, CLASS b ) { return CLASS(a.mVal * b.mVal); } \ friend CLASS operator/( CLASS a, CLASS b ) { return CLASS(a.mVal / b.mVal); } \ friend CLASS operator-( CLASS a ) { return CLASS(-a.mVal); } \ friend bool operator==( const CLASS a, const CLASS b ) { return a.mVal == b.mVal; } \ friend bool operator!=( const CLASS a, const CLASS b ) { return a.mVal != b.mVal; } \ friend bool operator>( CLASS a, CLASS b ) { return a.mVal > b.mVal; } \ friend bool operator<( CLASS a, CLASS b ) { return a.mVal < b.mVal; } \ friend bool operator>=( CLASS a, CLASS b ) { return a.mVal >= b.mVal; } \ friend bool operator<=( CLASS a, CLASS b ) { return a.mVal <= b.mVal; } \ private: \ T mVal; \ }; /// @class base::bool0 /// @brief Fundamental type auto-initialized as zero. /// @class base::int0 /// @brief Fundamental type auto-initialized as zero. /// @class base::uint0 /// @brief Fundamental type auto-initialized as zero. DECLARE_DISTINCT_TYPE( bool0, bool, CONV_FUNC_UNUSED ) DECLARE_DISTINCT_TYPE( int0, int , CONV_FUNC_UNUSED ) DECLARE_DISTINCT_TYPE( uint0, uint, CONV_FUNC_UNUSED ) #undef virtual } // namespace base #endif // BASE_TYPES_HH