From: John Maddock (John_Maddock_at_[hidden])
Date: 2000-01-08 07:55:56
>But regardless, does it matter? Can someone give a practical problem, for
which this sort of information is needed to provide a correct solution?
While traits are a good thing, and a general traits class would be useful,
this all smacks of a solution looking for a problem.<
There are two principal uses: optimisation and assertion checking.
Optimisation: If type T has a trivial destructor then don't bother calling
destructors on T.
Assertion checking: If T is not a built-in integral type then portability
assumptions may break down.
Dicission Making: What is the optimal way to pass T as an argument - as
const T (by value) or const T& (by reference) - in other words to implement
Smart adaption: If a method expecting a function object gets passed a
function pointer instead, we can automatically adjust (using is_pointer).
>So this is the way I see it:
"const int" is not an integral type (3.9.1p6), but
is a scalar type (3.9p10)
"int * const" is not a pointer type (3.9.2p3), but
is a scalar type (3.9p10)
"const int" is a cv-qualified integral type
"int * const" is a cv-qualified pointer type<
Yep thats right.
However - I worry about the complexity of type_traits and the number of
templates we seem to have acquired - in particular is_integral duplicates
numeric_limits<>::is_integral exactly - as implemented they are required to
always give the same result. Given that we are using section 3.9 as a
guide could we not depreciate is_builtin_integral and make is_integral
behave as is_builtin_integral does now? As an asside I think with this
change we could also remove the dependance on numeric_limits<> completely
(without increase in code size), and in doing so improve portability -
there does seem to be a problem with <limits> implementations in general.
OK now I'm going to throw in a radical idea - so feel free to shoot me
What if we bring back a type traits class as follows, which would be the
only documented member of type_types.hpp:
template <typename T>
unsigned int category = implementation_defined;
unsigned int modifiers = implementation_defined;
unsigned int properties = implementation_defined;
Each of the members of type_traits are bitmask types:
type_traits<>::category always has exactly one of the following bits set
(in other words ignors top level cv-modifiers):
Note I've not added values - but these are implemented as bitmasks.
In addition there may be composite categories for testing:
is_integral = is_signed_int|is_unsigned_int|is_char|is_bool,
is_builtin = is_integral|is_float|is_void,
is_scalar = is_builtin|is_pointer
type_traits<>::modifiers may have one of the following bits set:
Other masks for modifiers like restrict, __fastcall etc may be possible on
type_traits<>::properties may have one of the following bits set:
Again there may be other properties that could be added.
Usage would be something like:
type_traits<T>::properties & has_trivial_construct
type_traits<T>::category & is_signed_integral
Implementation would use a simplified form of our existing fundamentals
(which could be moved into the implementation namespace) - I think there is
an oportunity here both to reduce the amount of code, and the number of
classes, and work around the arguments we've been having about whether a
value can be called "type", and whether a cv-qualified int is an integral
type or not. On the other hand maybe not: I don't want to swap one lot of
indecision for another :-)
Feel free to be blunt!
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk