|
Boost : |
From: John Maddock (John_Maddock_at_[hidden])
Date: 2000-01-08 07:55:56
Paul,
>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
call_traits.
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)
Note that:
"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
down!!
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>
struct type_traits
{
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):
enum{
is_signed_int,
is_unsigned_int,
is_char,
is_bool,
is_void,
is_float,
is_pointer,
is_member_pointer,
is_reference,
ise_array,
is_class,
is_union,
is_enum
};
Note I've not added values - but these are implemented as bitmasks.
In addition there may be composite categories for testing:
enum{
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:
enum{
is_const,
is_volatile
};
Other masks for modifiers like restrict, __fastcall etc may be possible on
some platforms.
type_traits<>::properties may have one of the following bits set:
enum{
has_trivial_construct,
has_trivial_copy,
has_trivial_assign,
has_trivial_destruct,
is_POD
};
Again there may be other properties that could be added.
Usage would be something like:
type_traits<T>::properties & has_trivial_construct
or:
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!
- John.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk