Topic: Templates for host types' independancy.
Author: Vlad Harchev <vladhar@imimail.ssau.ru>
Date: 1998/08/17 Raw View
Here is a code that will be useful for porting libraries. I have implemented
and tested the similar code, and here i try to reproduce it. Here, in the
laboratory, i have no compiler installed, so i wasn't able to test it.
I believe that there are no bugs here - may be some typos. Especially
check the macro names like SHORT_MAX - may be i misspeled them.
It seems to me that the similar things must go in standart.
I be very pleased, if my name will be noticed in the headers that provide
the implementation of this template:
"Based on the idea of Vlad Harchev, vladhar@imimail.ssau.ru"
=====================================================cut-here==============
#include <limits.h> //for type sizes like INT_MAX
typedef long bigest_int_t; //the largest integer type, allowed as non-type
//template parameter. On some compilers, it's twice as larger as long -
// __int64 on BCC. This should be signed.
/* this template will never be used - it's specializations will be used
instead. Each of them will define the typedef member named 'type' -
the type, that suits such conditions.
*/
template struct __type_by_range_aux<bool is_signed,bool bigger_char,
bool bigger_short,bool bigger_int>
{ };
#define _EXPL_SPEC template<>
_EXPL_SPEC struct __type_by_range_aux<false,false,false,false>
{ typedef unsigned char type; };
_EXPL_SPEC struct __type_by_range_aux<true,false,false,false>
{ typedef signed char type; };
_EXPL_SPEC struct __type_by_range_aux<false,true,false,false>
{ typedef unsigned short type; };
_EXPL_SPEC struct __type_by_range_aux<true,true,false,false>
{ typedef signed short type; };
_EXPL_SPEC struct __type_by_range_aux<false,true,true,false>
{ typedef unsigned int type; };
_EXPL_SPEC struct __type_by_range_aux<true,true,true,false>
{ typedef signed int type; };
_EXPL_SPEC struct __type_by_range_aux<false,true,true,true>
{ typedef unsigned long type; };
_EXPL_SPEC struct __type_by_range_aux<true,true,true,true>
{ typedef signed long type; };
/* the members of this template are designed in a special way in order
to
avoid BCC enum bug. First parameter is the biggest value to hold, and
saecond - the smallest.
*/
template <bigest_int_t U_, bigest_int_t L_=0>
struct type_by_range
{
//these enums are temporary.
enum {
L1=L_, U1=U_, //avoids BCC enum bug
L = L1 < U1 ? L1 : U1, U = L1 < U1 ? U1 : L1, //get the real max and min
is_signed = (L < 0),
abs_L = L < 0 ? -L : L,
abs_U = U < 0 ? -U : U,
max_abs_val = abs_L > abs_U ? abs_L : abs_U,
//now we know, whether the type should be signed, and the max abs
//value to represent.
bigger_char = is_signed ?
(max_abs_val/SCHAR_MAX > 0 ) : (max_abs_val/UCHAR_MAX > 0 ),
bigger_short = is_signed ?
(max_abs_val/SHORT_MAX > 0 ) : (max_abs_val/USHORT_MAX > 0 ),
bigger_int = is_signed ?
(max_abs_val/INT_MAX > 0 ) : (max_abs_val/UINT_MAX > 0 )
}
typedef typename
__type_by_range_aux<is_signed,bigger_char,bigger_short,bigger_int>::type
type;
};
//examples of usage:
typedef type_by_range<365>::type day_t;
typedef type_by_range<200,-300>::type some_type;
/*
Ideas:
*) put auxilary templates in some namespace to avoid polluting the
global namespace or std::.
*) To add several type gates: for example:
smallest_type_by_range, optimal_type_by_range.
The second will be considered faster than first, but can be wider than
first also. This is compiler-specific and may depend on command line
options of compiler.
*) Template type_by_width can be added - returns type for the given width in
bits. In this case, the special long integer templates can be
introduced, that will provided the support for a types of arbitrary width.
Some problems:
According to draft, it's guaranteed, that the enum will be able to hold values
of type 'int', and it haven't to be able to hold anything bigger.
Most compilers overdone the draft in this way, so it seems there is no
trouble. Another approach - to make the stuff 'static const bigest_int_t'
members of the 'type_by_range' template and initiliaze it there. By it seems
to me that more compilers do not support such standart feature, than those
one that allow enum to hold something bigger than int.
*/
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Vlad Harchev <vladhar@imimail.ssau.ru>
Date: 1998/08/20 Raw View
If anybody is interested in it, here are the bugfixes in the send code:
The code for 'type_by_range' should be substituted with:
template <bigest_int_t U_, bigest_int_t L_=0>
struct type_by_range
{
//these enums are temporary.
enum {
L1=L_, U1=U_, //avoids BCC enum bug
L = L1 < U1 ? L1 : U1, U = L1 < U1 ? U1 : L1, //get the real max and min
is_signed = (L < 0),
abs_L = L < 0 ? -L : L,
abs_U = U < 0 ? -U : U,
depends_on_L = abs_L > abs_U,
max_abs_val = abs_L > abs_U ? abs_L : abs_U,
//now we know, whether the type should be signed, and the max abs
//value to represent.
bigger_char = is_signed ?
(depends_on_L ? abs_L > -SCHAR_MIN : max_abs_val > SCHAR_MAX ) : (max_abs_val >
UCHAR_MAX ),
bigger_short = is_signed ?
(depends_on_L ? abs_L > -SHRT_MIN : max_abs_val > SHRT_MAX ) : (max_abs_val >
USHRT_MAX ),
bigger_int = is_signed ?
(depends_on_L ? abs_L > -INT_MIN : max_abs_val > INT_MAX ) : (max_abs_val >
UINT_MAX ),
}
typedef typename
__type_by_range_aux<is_signed,bigger_char,bigger_short,bigger_int>::type type;
};
Previous version of the code will suggest not the smalest type if the upper bound of the
range was bigger than
{ the maximum value represented by that type minus 1} and if the lower bound of the range
has the value by 1 or 2
smaller than the minimum value representable by the type.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]