From: alf.p.steinbach+usenet@gmail.com   
      
   On 16.05.2012 06:23, Seungbeom Kim wrote:   
   > Hi all,   
   >   
   > The subject explains itself. Let's say you have a pair of objects, a and b,   
   > of an unsigned integer type U, and you want to calculate their difference   
   > in a signed integer type.   
   >   
   > Obviously you cannot simply write "a - b", because that will yield an   
   > unsigned integer value in modulo arithmetic. So you want to write   
   >   
   > S d = static_cast(a) - static_cast(b);   
   >   
   > for a signed integer type S.   
   >   
   > The problem is, how do you determine S? Of course, S should be large enough   
   > to represent all the values of U. To be safe, you could just use S=intmax_t   
   > for every U, but that might be an overkill; if U=uint16_t, then S=uint32_t   
   > is enough, and you don't want to use more expensive arithmetic in uint64_t   
   > or uint128_t. So, something like S=int_least[N+1]_t where N=numeric_limits   
   > ::digits() would be desirable (+1 because of the sign bit).   
   >   
   > Is there a way to automatically determine S from U?   
   >   
      
   I think this should work, although I recommend primarily to avoid using   
   unsigned types for numbers, and secondly, if one must, use `ptrdiff_t`   
   for differences (after all, that's what you get for a pointer difference):   
      
      
      
   #include    
   #include    
   using namespace std;   
      
   struct CompleteVoid {};   
      
   template< class Type > struct Next;   
   template<> struct Next { typedef unsigned char T; };   
   template<> struct Next { typedef unsigned char T; };   
   template<> struct Next { typedef short T; };   
   template<> struct Next { typedef unsigned short T; };   
   template<> struct Next { typedef int T; };   
   template<> struct Next { typedef unsigned T; };   
   template<> struct Next { typedef long T; };   
   template<> struct Next { typedef unsigned long T; };   
   template<> struct Next { typedef long long T; };   
   template<> struct Next { typedef unsigned long long T; };   
   template<> struct Next { typedef CompleteVoid T; };   
      
   template< bool condition, class A, class B >   
   struct Choose;   
      
   template< class A, class B >   
   struct Choose< true, A, B > { typedef A T; };   
      
   template< class A, class B >   
   struct Choose< false, A, B > { typedef B T; };   
      
   template< class Type >   
   struct NextLarger   
   {   
   private:   
    typedef typename Next::T NextUp;   
   public:   
    typedef typename Choose<   
    (sizeof(NextUp) > sizeof(Type)),   
    NextUp,   
    typename NextLarger::T   
    >::T T;   
   };   
      
   template<>   
   struct NextLarger   
   {   
   public:   
    typedef void T;   
   };   
      
   int main()   
   {   
    wcout   
    << "The signed type above & covering 'unsigned' is '"   
    << typeid( NextLarger::T ).name()   
    << "'."   
    << endl;   
   }   
      
      
      
   For g++ there is g++-specific function that produces readable type   
   names, I don't recall its name but you can easily find it.   
      
      
   Cheers & hth.,   
      
   - Alf   
      
      
   --   
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
    [ comp.lang.c++.moderated. First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|