Scott Zhong wrote:
> I try to implement type_traits using partial specialization as follows:
>
> template <class T> struct __remove_s { typedef T type; };
> template <class T> struct __remove_s<signed T> { typedef T type; };
> template <class T> struct __remove_s<unsigned T> { typedef T type; };
> template <class T> struct __remove_s<short T> { typedef T type; };
> template <class T> struct __remove_s<long T> { typedef T type; };
>
> template <class T> struct is_integral:
> __is_same<typename __remove_s<typename
> __remove_cv<T>::type>::type, int> { };
>
> But signed is actually a type and T is already a type, and signed int is
> a compound type.
signed int is a fundamental type (3.9.1). It's also an arithmetic
type, but it's not a compound type (3.9.2). Precise terminology is
important when discussing traits :)
Unlike constness or volatility, signedness is a property that's
inherent to integer types. It's not something that can be removed
or added. The "signed" in, say, "signed long," is a part of the
name of the type, not just some attribute. Ditto for signed short
or signed int. Think of long, short, and int as aliases for the
verbose forms of their names.
> When compiling the above code in MSVC 8.0, it would
> give an error that states "too many template arguments".
That's a poor error message. Gcc says:
error: long, short, signed or unsigned invalid for 'type name'
error: partial specialization 'S<T>' does not specialize any template
arguments
> I went ahead
> and read the book you had pointed to me, the implementation in there is
> using 3 enum? with a 3rd struct containing index_of template that would
> search though the enum with return value of greater than 0 if found, 0
> if not found. I decided to implement it a different way as follows:
[...]
> Not really sure the internal workings of a template, does it treat each
> specialization as an enum? My implementation does generate 5 template
> instantiation whenever is_integral is called, would that adversely
> affect performance? Please let me know if there is a better
> implementation.
I would suggest you start by defining what an integer type is.
Writing down the definition will be helpful in breaking up the
implementation of the trait into smaller, more manageable bits.
Here's how section 3.9 of the working draft of the C++ standard
defines an integral type:
A C++ integral type is one of:
bool, char, wchar_t, signed integer type, or unsigned integer
type
A signed integer type is one of: standard signed integer type,
or extended signed integer type
An unsigned integer type is one of: standard unsigned integer
type or extended unsigned integer type
A standard signed/unsigned integer type is one of: short, int,
long, long long unsigned short, unsigned, unsigned long, and
unsigned long long
An extended signed/unsigned integer type is one of: a set of
implementationdefined types
It should be relatively easy to model an implementation of the
trait based on the definition.
But before you start, since you already know that the trait (like
many others) is required to yield the same result when specialized
on a cvqualified type as when specialized on a plain type, you
might want to create some simple helper traits that will let you
remove any cvqualifications from types (remove_const,
remove_volatile, and remove_cv), or determine whether two types
are the same (is_same). These helper traits are also a required
part of the type traits interface (see 20.4.7) so by coding them
you'll be ahead of the game :)
Attached is my attempt at defining the helpers and the trait. Take
a look at it to see if it makes sense to you. As you can already
see there are a number of ways of implementing these critters. I
would encourage you to experiment with different approaches to see
which one you like best and how long each takes the compile with
which compiler. The goal should be to come up with an elegant,
compact implementation that's fast to compile and that generates
the least number of specializations of implementation classes
(deep template recursion is the enemy of compile time efficiency).
Martin
