C++ template metaprogramming学习笔记一

本文详细探讨了C++模板元编程的基础概念,包括Boost的type traits库,介绍了is_xxx系列metafunction的实现,如is_integral、is_float、is_function等,并讨论了is_same、is_convertible和is_base_and_derived等类型关系检查。同时,文章提到了编译期计算类型属性,如alignment_of和类型属性检查,强调了这些元编程技术在C++中的重要性。
概念:
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=falsebool arg3=falsebool arg4=falsebool arg5=falsebool arg6=falsebool arg7=falsebool arg8=falsebool 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=truebool arg3=truebool arg4=truebool arg5=truebool arg6=truebool arg7=truebool arg8=truebool 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_{};
is_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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值