C++ template metaprogramming学习笔记一

概念:
Metadata :能够在编译期被操作的东西就是元数据,分成两类:类型和非类型,这两类都可以做为模板参数。整数类型,函数的指针或引用,成员指针(这些都可以转化成整数,因此是合法的)
Metafunction :类模板,它的所有参数都是类型;
                             类,有公共的可访问的内嵌类;
多态:允许使用不同的参数类型的性质就是多态,字面上即“多种形式的能力”;
C++中,多态有两种:静态多态,即编译期多态;动态多态,即运行期多态;
编译期多态使得我们可以在编译期做出选择,而这正是我们所向往追求的。

Boosttype traits library:这是MPL的基石
以下代码抽自boost/或自己的替代实现,知其然,知其所以然,我们后面使用到的时候才可以了然于胸
1.    primary type
is_xxx
系列的metafunction具有成员value,而且我们只关心成员value的值为true/false

template <   bool  x  >   struct  bool_
{
       
static bool const value = x;        
       typedef bool_
<x> type;              
       typedef 
bool value_type;            
       
operator bool() const return x; } 
};
typedef bool_ < false >  false_;
typedef bool_
< true >  true_;

is_xxx系列派生自bool_,下面逐一给出is_xxx的实现
is_integral通过对integral类型进行特化达到

template < typename type >
struct  is_integral : false_ {} //  即默认所有类型均不是integral类型

 

//  at this moment, variadic template still has nothing to do with this condition
template < bool  arg0,  bool  arg1,  bool  arg2 = false bool  arg3 = false bool  arg4 = false bool  arg5 = false bool  arg6 = false bool  arg7 = false bool  arg8 = false bool  arg9 = false >
struct  ice_or
{
    
static const bool value = arg0+arg1+arg2+arg3+arg4+arg5+arg6+arg7+arg8+arg9;
}
;

template
< bool  arg0,  bool  arg1,  bool  arg2 = true bool  arg3 = true bool  arg4 = true bool  arg5 = true bool  arg6 = true bool  arg7 = true bool  arg8 = true bool  arg9 = true >
struct  ice_and
{
    
static const bool value = arg0*arg1*arg2*arg3*arg4*arg5*arg6*arg7*arg8*arg9;
}
;

// 然后对可枚举的integral类型进行特化,其中还有对应的const/volatile/const volatile版本

template <>   struct  is_integral < char > : true_... {} ;
template
<>   struct  is_integral < const   char > : true_... {} ;
template
<>   struct  is_integral < volatile   char > : true_... {} ;
template
<>   struct  is_integral < const   volatile   char > : true_... {} ;

 C++中的integral类型有以下:
bool / char / unsigned char / signed char / wchar_t / short / unsigned short / int / unsigned int / long / unsigned long / long long / unsigned long long
分别对以上类型进行特化,我们就可以得到完整的is_integral
is_float
的实现跟is_integral相同,c++中,float类型只有float/double/long double,还有对应的const/volatile/const volatile版本;

template < typename type >
struct is_void : false_ {} ;
template
<>   struct  is_void < void >  : true_ {} ;
template
<>   struct  is_void < const   void >  : true_ {} ;
template
<>   struct  is_void < const   volatile   void >  : true_ {} ;

Is_function使用variadic template实现,否则需要根据函数的参数个数一一进行特化,很麻烦,c++0x直接支持variadic templateconceptgcc已经实现了variadic template功能


template < typename type >
struct  is_function : false_ {} ;
template
< typename retType, typename ... argType >
struct  is_function < retType ( * )(argType...) >  : true_ {} ;
template < typename type >
struct  is_member_function : false_ {} ;
template
< typename retType, typename classType, typename ... argType >
struct  is_member_function < retType (classType:: * )(argType...) >  : true_ {} ;

template < typename type >   struct  is_array : false_... {} ;
template
< typename type,  int  N >   struct  is_array < type[N] >  : true_... {} ;
template
< typename type >   struct  is_array < type[] >  : true_... {} ;
//  然后是对应的const/volatile/const volatile版本true_{};
i s_member_pointer的实现类似于 is_function,其中, is_member_pointer分为两种: 1,类成员数据指针; 2,类成员函数指针

template < typename type >
struct  is_member_pointer :false_ {} ;
template
< typename dataType, typename classType >
struct  is_member_pointer < dataType classType:: *>  : true_ {} ;
template
< typename retType, typename classType, … argType >
struct  is_member_pointer < retype (classType:: * )(argType…) >  : true_ {} ;
// 还有对应的const/volatile/const volatile版本

template < typename type >
struct  is_pointer : false_ {} ;
template
< typename type >
struct  is_ponter < type *>  : true_ {} ;
template
< typename type >
struct  is_pointer : is_function < type > {} ;
template
< typename type >
struct  is_pointer : is_member_pointer < type > {} ;

 


template < typename type >
struct  is_reference : false_ {} ;
template
< typename type >
struct  is_reference < type &>  : true_ {} ;
//  还有对应的const/volatile/const volatile版本

 C++中的类类型包括:class/struct/union定义的类型,对于类类型,可以定义其类成员指针,包括成员数据指针及成员函数指针,boost就是利用这个性质来区分是否为类类型

template < typename type >   char  class_helper( int  type:: * );
template
< typename type >   int   class_helper(...);

template
< typename type >
struct  is_class_helper
{
    
static const bool value = sizeof(class_helper<type>(0))==sizeof(char? true : false;
}
;

template
< typename type >
struct  is_class : bool_ < is_class_helper < type > ::value > {} ;

现在,剩下is_union/is_enum未实现,这几个比较麻烦,需要编译器提供相当的支持,boost提供保守的支持,就是将is_union/is_enum都默认为false_

2.    secondary type

           template < typename type >
struct  is_arithmetic : boos_ <ice_or<is_integral<type>::value, is_float<type>::value>::value>{} ;

is_fundamental的实现:包含算术类型和void类型

template < typename type >
struct  is_fundamental: bool_ <ice_or<is_arithmetic<type>::value, is_void<type>::value>::value>{} ;


根据C++标准,复合类型包括数组/函数/指针/引用/类类型/枚举/成员指针,或者说,除了基础类型,其它的都是复合类型,而基础类型则只包括算术类型和void类型。

template < typename type >
struct  is_compound: bool_ <! is_fundamental < type > ::value > {} ;

C++中,对象是指除了函数和引用之外的所有东西

template < typename type >
struct  is_object: bool_ <!ice_or<is_function<type>::value, is_reference<type>::value>::value>{};

根据C++定义,标量类型包括算术类型/枚举类型/指针类型

template < typename type >
struct  is_scalar: bool_ < ice_or<is_arithmetic<type>::value, is_pointer<type>::value, is_member_pointer<type>::value>::value>{};

枚举类型需要编译器的支持,boost中保守地将其置为false_。

3.    type property

alignment_of用于编译期计算出类型的对齐长度,alginment_of还需要对void进行特化

template < typename type >
struct  alignment_of_helper {
    
char c;
    type t;
}
;
template
< typename type >
struct  alignment_of {
    
static const int value = (sizeof(alignment_of_helper)-sizeof(c))<size(type)?(sizeof(alignment_of_helper)-sizeof(c)):sizeof(type);
}
;

 is_empty

template < typename type >
struct  is_empty_helper : type {} ;
template
< typename type,  bool  isClass = false >
struct  is_empty_helper1
{
        
static const bool value = false;
}
;
template
< typename type >
struct  is_empty_helper1 < type, true >
{
    
static const bool value = (sizeof(is_empty_helper<type>== sizeof(type));
}
;
template
< typename type >
struct  is_empty : bool_ < is_empty_helper1 < type, is_class < type > ::value > {} ;

如果类类型是多态的,即类具有虚函数
template < typename Type,  bool  isClass = false >
struct  is_polymorphic_helper
{
    
static const bool value = false;
}
;

template
< typename Type >
struct  is_polymorphic_helper < Type, true >
{
    typedef typename remove_cv
<Type>::type ncvType;
    
struct base1 : ncvType{~base1(){}};
    
struct base2 : ncvType{virtual ~base2(){}};
    
static const bool value = (sizeof(base1) == sizeof(base2));
}
;

template
< typename Type >
struct  is_polymorphic : bool_ < is_polymorphic_helper < Type, is_class < Type > ::value > ::value > {} ;


4.    more type property
has_nothrow_assign / has_nothrow_constructor / has_nothrow_copy / has_trivial_assign / has_trivial_constructor / has_trivial_copy / is_pod / is_stateless
的实现,都需要编译器支持

5.    relationship between types

    template < typename type1, typename type2 >
struct  is_same : false_ {} ;
template
< typename type >
struct  is_same < type,type >  : true_ {}


is_convertible

template < typename to >
char  convertible_helper(to);
template
< typename to >
int  convertible_helper(...);
template
< typename from, typename to >
struct  is_convertible_helper
{
    
static from m;
    
static const bool value = (sizeof(convertible_helper<to>(m)) == sizeof(char));
}
;

template
< typename from, typename to >
struct  is_convertible : bool_ < is_convertible_helper < from,to > ::value > {} ;
is_base_and_derived

template < typename  base , typename derived >
struct  is_base_and_derived : bool_ < ice_and < is_class < base > ::value, is_class < derived > ::value, is_convertible < derived,  base > ::value > ::value > {} ;

6.    type transformation

template < typename Type >
struct  remove_const
{
    typedef Type type;
}
;
template
< typename Type >
struct  remove_const < const  Type >
{
    typedef Type type;
}
;
template
< typename Type >
struct  remove_const < const   volatile  Type >
{
    typedef Type 
volatile type;
}
;


template < typename Type >
struct  remove_volatile
{
    typedef Type type;
}
;
template
< typename Type >
struct  remove_volatile < volatile  Type >
{
    typedef Type type;
}
;
template
< typename Type >
struct  remove_volatile < const   volatile  Type >
{
    typedef Type 
const type;
}
;

template < typename Type >
struct  remove_cv
{
    typedef typename remove_volatile
<typename remove_const<Type>::type>::type type;
}
;


template < typename Type >
struct  remove_reference
{
    typedef Type type;
}
;

template
< typename Type >
struct  remove_reference < Type &>
{
    typedef Type type;
}
;

template < typename Type >
struct  remove_pointer
{
    typedef Type type;
}
;

template
< typename Type >
struct  remove_pointer < Type *>
{
    typedef Type type;
}
;

template < typename Type >
struct  add_reference
{
    typedef Type
& type;
}
;

template
< typename Type >
struct  add_reference < Type &>
{
    typedef Type type;
}
;

template < typename Type >
struct  add_pointer
{
    typedef Type
* type;
}
;


template < typename Type >
struct  add_const
{
    typedef Type 
const type;
}
;

template
< typename Type >
struct  add_const < const  Type >
{
    typedef Type type;
}
;

以上的type_trait实现只在conceptgcc下面测试通过并且测试是相当简单的,给出测试用例,如果需要使用type_trait,我们仍然需要使用boost中的mpl
struct  foo {} ;

struct  vfoo {virtual ~vfoo(){}} ;

struct   base {} ;
struct  derived :  base {} ;

void  bar( int  v, char  b)
{}

int  main()
{
    typedef 
int (*funcptr)(int,char);
    typedef 
void (foo::*memfunptr)(int,char);
    printf(
"funcptr is pointer : %d ", is_pointer<funcptr>::value);
    printf(
"int is pointer : %d ", is_pointer<int>::value);
    printf(
"int* is pointer : %d ", is_pointer<int*>::value);
    printf(
"int is class : %d ", is_class<int>::value);
    printf(
"foo is class : %d ", is_class<foo>::value);
    printf(
"int is array : %d ", is_array<int>::value);
    printf(
"int[] is array : %d ", is_array<int[]>::value);
    printf(
"const int[] is array : %d ", is_array<const int[]>::value);
    printf(
"const int[10] is array : %d ", is_array<const int[10]>::value);
    printf(
"const int*[10] is array : %d ", is_array<const int*[10]>::value);
    printf(
"int is reference : %d ", is_reference<int>::value);
    printf(
"int& is reference : %d ", is_reference<int&>::value);
    printf(
"const int& is reference : %d ", is_reference<const int&>::value);

    printf(
"memfunptr is member function pointer : %d ", is_member_pointer<memfunptr>::value);
    printf(
"int is member function pointer : %d ", is_member_pointer<int>::value);
    printf(
"int is arithmetic : %d ", is_arithmetic<int>::value);
    printf(
"int* is arithmetic : %d ", is_arithmetic<int*>::value);
    printf(
"double is fundamental : %d ", is_fundamental<double>::value);
    printf(
"void is fundamental : %d ", is_fundamental<void>::value);
    printf(
"void* is fundamental : %d ", is_fundamental<void*>::value);
    printf(
"foo is compound : %d ", is_compound<foo>::value);
    printf(
"int is compound : %d ", is_compound<int>::value);
    printf(
"int[] is compound : %d ", is_compound<int[]>::value);
    printf(
"int is object : %d ", is_object<int>::value);
    printf(
"int& is object : %d ", is_object<int&>::value);
    printf(
"foo is object : %d ", is_object<foo>::value);
    printf(
"funcptr is object : %d ", is_object<funcptr>::value);
    printf(
"int is scalar : %d ", is_scalar<int>::value);
    printf(
"int& is scalar : %d ", is_scalar<int&>::value);
    printf(
"foo alignment : %d ", alignment_of<foo>::value);
    printf(
"void alignment : %d ", alignment_of<void>::value);
    printf(
"long double alignment : %d ", alignment_of<long double>::value);
    printf(
"int is empty : %d ", is_empty<int>::value);
    printf(
"foo is empty : %d ", is_empty<foo>::value);
    printf(
"foo is polymorphic : %d ", is_polymorphic<foo>::value);
    printf(
"int is polymorphic : %d ", is_polymorphic<int>::value);
    printf(
"vfoo is polymorphic : %d ", is_polymorphic<vfoo>::value);
    printf(
"int float is convertible : %d ", is_convertible<int,float>::value);
    printf(
"int* float* is convertible : %d ", is_convertible<int*,float*>::value);
    printf(
"double float is convertible : %d ", is_convertible<double,float>::value);
    printf(
"foo vfoo is convertible : %d ", is_convertible<foo, vfoo>::value);
    printf(
"base derived is convertible : %d ", is_convertible<base, derived>::value);
    printf(
"derived base is convertible : %d ", is_convertible<derived, base>::value);
    
return 0;
}

附带上部分习题解答:
#include  < typeinfo >
#include 
< cstdio >
#include 
< stdbool.h >
#include 
< string .h >
#include 
< iostream >
using   namespace  std;

template
< typename type1, typename type2 >
struct  is_same
{
    
const static bool value = false;
}
;


template
< typename type >
struct  is_same < type,type >
{
    
const static bool value = true;
}
;

#if  0
template
< typename Type >
struct  add_const_ref
{
    typedef 
const Type& type;
}
;

template
< typename Type >
struct  add_const_ref < const  Type >
{
    typedef 
const Type& type;
}
;

template
< typename Type >
struct  add_const_ref < volatile  Type >
{
    typedef 
const Type& type;
}
;

template
< typename Type >
struct  add_const_ref < const   volatile  Type >
{
    typedef 
const Type& type;
}
;

template
< typename Type >
struct  add_const_ref < Type &>
{
    typedef Type type;
}
;


template
< typename Type >
struct  add_const_ref < const  Type &>
{
    typedef Type type;
}
;


template
< typename Type >
struct  add_const_ref < volatile  Type &>
{
    typedef Type type;
}
;


template
< typename Type >
struct  add_const_ref < const   volatile  Type &>
{
    typedef Type type;
}
;

template
< typename c, typename x, typename y >
struct  replace_type
{
    typedef c type;
}
;

template
< typename c, typename x, typename y >
struct  replace_type < const  c, x, y >
{
    typedef typename replace_type
<c,x,y>::type const type;
}
;

template
< typename c, typename x, typename y >
struct  replace_type < volatile  c, x, y >
{
    typedef typename replace_type
<c,x,y>::type volatile type;
}
;

template
< typename c, typename x, typename y >
struct  replace_type < const   volatile  c, x, y >
{
    typedef typename replace_type
<c,x,y>::type const volatile type;
}
;

template
< typename x, typename y >
struct  replace_type < x,x,y >
{
    typedef y type;
}
;

template
< typename x, typename y >
struct  replace_type < const  x,x,y >
{
    typedef y 
const type;
}
;

template
< typename x, typename y >
struct  replace_type < volatile  x,x,y >
{
    typedef y 
volatile type;
}
;

template
< typename x, typename y >
struct  replace_type < const   volatile  x,x,y >
{
    typedef y 
const volatile type;
}
;

template
< typename c, typename x, typename y >
struct  replace_type < c & , x, y >
{
    typedef typename replace_type
<c,x,y>::type& type;
}
;

template
< typename c, typename x, typename y >
struct  replace_type < c * , x, y >
{
    typedef typename replace_type
<c,x,y>::type* type;
}
;

template
< typename c, typename x, typename y,  int  size >
struct  replace_type < c[size],x,y >
{
    typedef typename replace_type
<c,x,y>::type  tempType;
    typedef tempType type[size];
}
;

template
< typename c, typename x, typename y >
struct  replace_type < c( * )(),x,y >
{
    typedef typename replace_type
<c,x,y>::type retType;
    typedef retType (
*type)();
}
;

template
< typename c, typename arg1, typename x, typename y >
struct  replace_type < c( * )(arg1),x,y >
{
    typedef typename replace_type
<c,x,y>::type retType;
    typedef typename replace_type
<arg1,x,y>::type arg1Type;
    typedef retType (
*type)(arg1Type);
}
;

template
< typename c, typename arg1, typename arg2, typename x, typename y >
struct  replace_type < c( * )(arg1,arg2),x,y >
{
    typedef typename replace_type
<c,x,y>::type retType;
    typedef typename replace_type
<arg1,x,y>::type arg1Type;
    typedef typename replace_type
<arg2,x,y>::type arg2Type;
    typedef retType (
*type)(arg1Type,arg2Type);
}
;

// 原来想通过variadic template实现,尝试后未能成功
template
< typename c, typename ClassType, typename x, typename y >
struct  replace_type < c(ClassType:: * )(),x,y >
{
    typedef typename replace_type
<c,x,y>::type retType;
    typedef typename replace_type
<ClassType,x,y>::type classType;
    typedef retType (classType::
*type)();
}
;

template
< typename c, typename ClassType, typename arg1, typename x, typename y >
struct  replace_type < c(ClassType:: * )(arg1),x,y >
{
    typedef typename replace_type
<c,x,y>::type retType;
    typedef typename replace_type
<ClassType,x,y>::type classType;
    typedef typename replace_type
<arg1,x,y>::type arg1Type;
    typedef retType (classType::
*type)(arg1Type);
}
;

template
< typename c, typename ClassType, typename arg1, typename arg2, typename x, typename y >
struct  replace_type < c(ClassType:: * )(arg1,arg2),x,y >
{
    typedef typename replace_type
<c,x,y>::type retType;
    typedef typename replace_type
<ClassType,x,y>::type classType;
    typedef typename replace_type
<arg1,x,y>::type arg1Type;
    typedef typename replace_type
<arg2,x,y>::type arg2Type;
    typedef retType (classType::
*type)(arg1Type,arg2Type);
}
;
#endif

template
< typename Type >
struct  type_descriptor {
    
static const char *name;
    
operator const char*()
    
{
        
return name;
    }

}
;


template
< typename Type >   const   char *  type_descriptor < Type > ::name  =   " Unknow type " ;
template
<>   const   char *  type_descriptor < char > ::name  =   " char " ;
template
<>   const   char *  type_descriptor < const   char > ::name  =   " const char " ;
template
<>   const   char *  type_descriptor < volatile   char > ::name  =   " volatile char " ;
template
<>   const   char *  type_descriptor < const   volatile   char > ::name  =   " const volatile char " ;
template
<>   const   char *  type_descriptor < unsigned  char > ::name  =   " unsigned char " ;
template
<>   const   char *  type_descriptor < const  unsigned  char > ::name  =   " const unsigned char " ;
template
<>   const   char *  type_descriptor < volatile  unsigned  char > ::name  =   " volatile unsigned char " ;
template
<>   const   char *  type_descriptor < const   volatile  unsigned  char > ::name  =   " const volatile unsigned char " ;
template
<>   const   char *  type_descriptor < signed  char > ::name  =   " signed char " ;
template
<>   const   char *  type_descriptor < const  signed  char > ::name  =   " const signed char " ;
template
<>   const   char *  type_descriptor < volatile  signed  char > ::name  =   " volatile signed char " ;
template
<>   const   char *  type_descriptor < const   volatile  signed  char > ::name  =   " const volatile signed char " ;
template
<>   const   char *  type_descriptor < short > ::name  =   " short " ;
template
<>   const   char *  type_descriptor < const   short > ::name  =   " const short " ;
template
<>   const   char *  type_descriptor < volatile   short > ::name  =   " volatile short " ;
template
<>   const   char *  type_descriptor < const   volatile   short > ::name  =   " const volatile short " ;
template
<>   const   char *  type_descriptor < unsigned  short > ::name  =   " unsigned short " ;
template
<>   const   char *  type_descriptor < const  unsigned  short > ::name  =   " const unsigned short " ;
template
<>   const   char *  type_descriptor < volatile  unsigned  short > ::name  =   " volatile unsigned short " ;
template
<>   const   char *  type_descriptor < const   volatile  unsigned  short > ::name  =   " const volatile unsigned short " ;
template
<>   const   char *  type_descriptor < int > ::name  =   " int " ;
template
<>   const   char *  type_descriptor < const   int > ::name  =   " const int " ;
template
<>   const   char *  type_descriptor < volatile   int > ::name  =   " volatile int " ;
template
<>   const   char *  type_descriptor < const   volatile   int > ::name  =   " const volatile int " ;
template
<>   const   char *  type_descriptor < unsigned  int > ::name  =   " unsigned int " ;
template
<>   const   char *  type_descriptor < const  unsigned  int > ::name  =   " const unsigned int " ;
template
<>   const   char *  type_descriptor < volatile  unsigned  int > ::name  =   " volatile unsigned int " ;
template
<>   const   char *  type_descriptor < const   volatile  unsigned  int > ::name  =   " const volatile unsigned int " ;
template
<>   const   char *  type_descriptor < long > ::name  =   " long " ;
template
<>   const   char *  type_descriptor < const   long > ::name  =   " const long " ;
template
<>   const   char *  type_descriptor < volatile   long > ::name  =   " volatile long " ;
template
<>   const   char *  type_descriptor < const   volatile   long > ::name  =   " const volatile long " ;
template
<>   const   char *  type_descriptor < unsigned  long > ::name  =   " unsigned long " ;
template
<>   const   char *  type_descriptor < const  unsigned  long > ::name  =   " const unsigned long " ;
template
<>   const   char *  type_descriptor < volatile  unsigned  long > ::name  =   " volatile unsigned long " ;
template
<>   const   char *  type_descriptor < const   volatile  unsigned  long > ::name  =   " const volatile unsigned long " ;
template
<>   const   char *  type_descriptor < long   long > ::name  =   " long long " ;
template
<>   const   char *  type_descriptor < const   long   long > ::name  =   " const long long " ;
template
<>   const   char *  type_descriptor < volatile   long   long > ::name  =   " volatile long long " ;
template
<>   const   char *  type_descriptor < const   volatile   long   long > ::name  =   " const volatile long long " ;
template
<>   const   char *  type_descriptor < unsigned  long   long > ::name  =   " unsigned long long " ;
template
<>   const   char *  type_descriptor < const  unsigned  long   long > ::name  =   " const unsigned long long " ;
template
<>   const   char *  type_descriptor < volatile  unsigned  long   long > ::name  =   " volatile unsigned long long " ;
template
<>   const   char *  type_descriptor < const   volatile  unsigned  long   long > ::name  =   " const volatile unsigned long long " ;
template
<>   const   char *  type_descriptor < float > ::name  =   " float " ;
template
<>   const   char *  type_descriptor < const   float > ::name  =   " const float " ;
template
<>   const   char *  type_descriptor < volatile   float > ::name  =   " volatile float " ;
template
<>   const   char *  type_descriptor < const   volatile   float > ::name  =   " const volatile float " ;
template
<>   const   char *  type_descriptor < double > ::name  =   " double " ;
template
<>   const   char *  type_descriptor < const   double > ::name  =   " const double " ;
template
<>   const   char *  type_descriptor < volatile   double > ::name  =   " volatile double " ;
template
<>   const   char *  type_descriptor < const   volatile   double > ::name  =   " const volatile double " ;
template
<>   const   char *  type_descriptor < long   double > ::name  =   " long double " ;
template
<>   const   char *  type_descriptor < const   long   double > ::name  =   " const long double " ;
template
<>   const   char *  type_descriptor < volatile   long   double > ::name  =   " volatile long double " ;
template
<>   const   char *  type_descriptor < const   volatile   long   double > ::name  =   " const volatile long double " ;

template
< typename Type >
struct  type_descriptor < Type *> {
    
operator const char*()
    
{
        
static char name[1024];
        strcpy(name, 
"pointer to ");
        strcat(name, type_descriptor
<Type>());
        
return name;
    }

}
;

template
< typename Type >
struct  type_descriptor < Type &> {
    
operator const char*()
    
{
        
static char name[1024];
        strcpy(name, 
"reference to ");
        strcat(name, type_descriptor
<Type>());
        
return name;
    }

}
;

template
< typename Type,  int  size >
struct  type_descriptor < Type[size] > {
    
operator const char*()
    
{
        
static char name[1024];
        strcpy(name, 
"array of ");
        strcat(name, type_descriptor
<Type>());
        
char temp[256= {0};
        sprintf(temp, 
" which size = %d", size);
        strcat(name, temp);
        
return name;
    }

}
;

template
< typename retType >
struct  type_descriptor < retType( * )() >
{
    
operator const char*()
    
{
        
static char name[1024];
        strcpy(name, 
"function return ");
        strcat(name, type_descriptor
<retType>());
        strcat(name, 
" and has no argument");
        
return name;
    }

}
;

template
< typename retType, typename argType >
struct  type_descriptor < retType( * )(argType) >
{
    
operator const char*()
    
{
        
static char name[1024];
        strcpy(name, 
"function return ");
        strcat(name, type_descriptor
<retType>());
        strcat(name, 
" and with ");
        strcat(name, type_descriptor
<argType>());
        strcat(name, 
" as first argument");
        
return name;
    }

}
;

template
< typename retType, typename arg1Type, typename arg2Type >
struct  type_descriptor < retType( * )(arg1Type, arg2Type) >
{
    
operator const char*()
    
{
        
static char name[1024];
        strcpy(name, 
"function return ");
        strcat(name, type_descriptor
<retType>());
        strcat(name, 
" and with ");
        strcat(name, type_descriptor
<arg1Type>());
        strcat(name, 
" as first argument, ");
        strcat(name, type_descriptor
<arg2Type>());
        strcat(name, 
" as second argument");
        
return name;
    }

}
;

int  main()
{
    cout
<<"type_descriptor<const int* (*)(char& (*)(short), double*)>" << type_descriptor<const int* (*)(char& (*)(short), double*)>();
    printf(
"add_const_ref<int>::type = %s ", typeid(add_const_ref<int>::type).name());
    printf(
"add_const_ref<int>::type == const int& : %d ", is_same<add_const_ref<int>::type, const int&>::value);
    printf(
"add_const_ref<volatile int>::type == const int& : %d ", is_same<add_const_ref<volatile int>::type, const int&>::value);
    printf(
"add_const_ref<volatile int&>::type == int : %d ", is_same<add_const_ref<volatile int&>::type, int>::value);

    printf(
"replace_type<int,int,char>::type == char : %d ", is_same<replace_type<int,int,char>::type, char>::value);
    printf(
"replace_type<const int,int,char>::type == char : %d ", is_same<replace_type<const int,int,char>::type, const char>::value);
    printf(
"replace_type<int(*)(int,char),int,short>::type == short(*)(short,char) : %d ",  is_same<replace_type<int(*)(int,char),int,short>::type, short(*)(short,char)>::value);
    printf(
"replace_type<int(*)(const int,int (*)()),int,short>::type == short(*)(const short, short(*)()) : %d ",  is_same<replace_type<int(*)(const intint(*)()),int,short>::type, short(*)(const short,short(*)())>::value);
    printf(
"replace_type<int[10],int,char>::type == char[10] : %d ", is_same<replace_type<int[10],int,char>::type, char[10]>::value);
    printf(
"replace_type<int[10],int,char>::type = %s ", typeid(replace_type<int[10],int,char>::type).name());
    printf(
"replace_type<int[10],char,char>::type == int[10] : %d ", is_same<replace_type<int[10],char,char>::type, int[10]>::value);
    printf(
"replace_type<int[10],char,char>::type = %s ", typeid(replace_type<int[10],char,char>::type).name());
    
return 0;
}

你可能感兴趣的:(C++ template metaprogramming学习笔记一)