19.2 Determining Compound Types

Ru-Brd

Compound types are types constructed from other types. Simple compound types include plain types, pointer types, reference types, and even array types. They are constructed from a single base type. Class types and function types are also compound types, but their composition can involve multiple types (for parameters or members ). Simple compound types can be classified using partial specialization. We start with a generic definition of a traits class describing compound types other than class types and enumeration types (the latter are treated separately):

  // types/type2.hpp  template<typename T>  class CompoundT {  // primary template  public:      enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 0,             IsFuncT = 0, IsPtrMemT = 0 };      typedef T BaseT;      typedef T BottomT;      typedef CompoundT<void> ClassT;  }; 

The member type BaseT is a synonym for the immediate type on which the template parameter type T builds. BottomT , on the other hand, refers to the ultimate nonpointer, nonreference , and nonarray type on which T is built. For example, if T is int** , then BaseT would be int* , and BottomT would be int . For pointer-to-member types, BaseT is the type of the member, and ClassT is the class to which the member belongs. For example, if T is a pointer-to-member function of type int(X::*)() , then BaseT is the function type int() , and ClassT is X . If T is not a pointer-to-member type, the ClassT is CompoundT<void> (an arbitrary choice; you might prefer a nonclass).

Partial specializations for pointers and references are fairly straightforward:

  // types/type3.hpp  template<typename T>  class CompoundT<T&> {  // partial specialization for references  public:      enum { IsPtrT = 0, IsRefT = 1, IsArrayT = 0,             IsFuncT = 0, IsPtrMemT = 0 };      typedef T BaseT;      typedef typename CompoundT<T>::BottomT BottomT;      typedef CompoundT<void> ClassT;  };  template<typename T>  class CompoundT<T*> {  // partial specialization for pointers  public:      enum { IsPtrT = 1, IsRefT = 0, IsArrayT = 0,             IsFuncT = 0, IsPtrMemT = 0 };      typedef T BaseT;      typedef typename CompoundT<T>::BottomT BottomT;      typedef CompoundT<void> ClassT;  }; 

Arrays and pointers to members can be treated using the same technique, but it may come as a surprise that the partial specializations involve more template parameters than the primary template:

  // types/type4.hpp  #include <stddef.h>  template<typename T, size_t N>  class CompoundT <T[N]> {  // partial specialization for arrays  public:      enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 1,             IsFuncT = 0, IsPtrMemT = 0 };      typedef T BaseT;      typedef typename CompoundT<T>::BottomT BottomT;      typedef CompoundT<void> ClassT;  };  template<typename T>  class CompoundT <T[]> {  // partial specialization for empty arrays  public:      enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 1,             IsFuncT = 0, IsPtrMemT = 0 };      typedef T BaseT;      typedef typename CompoundT<T>::BottomT BottomT;      typedef CompoundT<void> ClassT;  };  template<typename T, typename C>  class CompoundT <T C::*> {  // partial specialization for pointer-to-members  public:      enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 0,             IsFuncT = 0, IsPtrMemT = 1 };      typedef T BaseT;      typedef typename CompoundT<T>::BottomT BottomT;      typedef C ClassT;  }; 

The watchful reader may have noted that the definition of the BottomT member requires the recursive instantiation of the CompoundT template for various types T . The recursion ends when T is no longer a compound type; hence the generic template definition is used (or when T is a function type, as we see later on).

Function types are harder to recognize. In the next section we use fairly advanced template techniques to recognize function types.

Ru-Brd


C++ Templates
C++ Templates: The Complete Guide
ISBN: 0201734842
EAN: 2147483647
Year: 2002
Pages: 185

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net