Taocp didn't take long. I felt that the math knowledge was too deep and I had been away from school for many years. I couldn't remember a lot of basic knowledge, so I ended my study of taocp, go to C ++ template metaprogramming. After reading the second chapter of the book, there is an interesting exercise about type traits, which is to imitate the cdecl command to describe a C ++ type using pseudo-English, for example, for char * (* []) (), "array of pointer to function returning pointer to char" is output ". The procedure is as follows:
# Include <iostream >#include <cstring> const int maxlen_type_descriptor = 200; Template <typename T> struct type_descriptor {operator const char * () {return name _;} static const char * Name _ ;}; template <typename T> const char * type_descriptor <t >:: name _ = "unkown type "; template <> const char * type_descriptor <char>: Name _ = "char"; Template <> const char * type_descriptor <short >:: name _ = "short "; template <> const char * type_descriptor <int>: Name _ = "int"; Template <> const char * type_descriptor <long >:: name _ = "long "; template <> const char * type_descriptor <long>: Name _ = "long"; Template <> const char * type_descriptor <unsigned char> :: name _ = "unsigned char"; Template <> const char * type_descriptor <unsigned short>: Name _ = "unsigned short "; template <> const char * type_descriptor <unsigned int>: Name _ = "unsigned int"; Template <> const char * type_descriptor <unsigned long> :: name _ = "unsigned long"; Template <> const char * type_descriptor <unsigned long>: Name _ = "unsigned long "; template <> const char * type_descriptor <float>: Name _ = "float"; Template <> const char * type_descriptor <double >:: name _ = "double "; template <> const char * type_descriptor <long double>: Name _ = "Long Double"; Template <> const char * type_descriptor <void>: Name _ = "Void "; template <> const char * type_descriptor <bool>: Name _ = "bool "; |
This code first defines the main template of type_descriptor, which has a type conversion operator function and a static constant character pointer pointing to the type description string. Operator const char * () enables this type to be directly used for stream output, for example, cout <type_descriptor <…> (); The subsequent Code defines the static constant character pointer used by the main template, which points to "unknown type". If type_descriptor fails to use a special template when it is instantiated, the "unknown type" description is displayed. Next, it is the static constant character pointer definition for the type_descriptor special version of 15 C ++ basic types (fundamental types), pointing to their respective description strings. After defining the special version of the basic type, it is now the turn to compound types and the type with the CV qualifier. The program is as follows:
Template <typename T> struct type_descriptor <t *> {operator const char * () {static char name [maxlen_type_descriptor]; strcpy (name, "pointer to"); strcat (name, type_descriptor <t> (); Return name ;}}; template <typename T> struct type_descriptor <t & >{ operator const char * () {static char name [maxlen_type_descriptor]; strcpy (name, "reference to"); strcat (name, type_descriptor <t> (); Return name ;}}; template <typename T> struct type_descriptor <t const> {operator const char * () {static char name [maxlen_type_descriptor]; strcpy (name, type_descriptor <t> ()); strcat (name, "const"); Return name ;}}; template <typename T> struct type_descriptor <t volatile> {operator const char *() {static char name [maxlen_type_descriptor]; strcpy (name, type_descriptor <t> (); strcat (name, "volatile"); Return name ;}}; template <typename T> struct type_descriptor <t []> {operator const char * () {static char name [maxlen_type_descriptor]; strcpy (name, "array "); strcat (name, type_descriptor <t> (); Return name ;}}; template <typename r> struct type_descriptor <R (*)> {operator const char *() {static char name [maxlen_type_descriptor]; strcpy (name, "pointer to function returning"); strcat (name, type_descriptor <r> (); Return name ;}}; template <typename R, typename A> struct type_descriptor <R (*) (a)> {operator const char * () {static char name [maxlen_type_descriptor]; strcpy (name, "pointer to function with"); strcat (name, type_descriptor <A> (); strcat (name, "returning"); strcat (name, type_descriptor <r> (); Return name ;}}; |
This piece of code processes the special features of pointers, references, arrays, CV delimiters, non-Argument functions, single-Argument functions, and Other types respectively. Each bitwise version defines its own operator const char * (), each of which has a local static character array used to store its own type description string, the description string is generated recursively by adding a specific string (such as "pointer of", "reference of", and "array of") to the type_descriptor template of a more basic type. The main () for testing and the running results are as follows:
Int main () {STD: cout <type_descriptor <int> () <STD: Endl; STD: cout <type_descriptor <char *> () <STD: Endl; STD: cout <type_descriptor <short const * &> () <STD: Endl; STD :: cout <type_descriptor <long const * volatile> () <STD: Endl; STD: cout <type_descriptor <char * (* [])> () <STD: Endl; STD: cout <type_descriptor <char * (* []) (Int &)> () <STD: Endl; return 0 ;}Output:Intpointer to charreference to pointer to short constpointer to long const volatilearray of pointer to function returning pointer to chararray of pointer to function with reference to int returning pointer to Char |
Of course, this type_descriptor has many shortcomings, such as: the length of the description string is limited, the function type of more parameters is not considered, and the user-defined type is not considered.