模板元编程:接受一个复合类型C作为第一个参数,并将其中的类型A替换为类型B
2010-09-01 21:14
183 查看
原题:http://topic.csdn.net/u/20100831/16/a6bf13c3-8002-4c5a-9746-b827deb20686.html?85864" target=_blank> http://topic.csdn.net/u/20100831/16/a6bf13c3-8002-4c5a-9746-b827deb20686.html?21825
定义:
1. IsSameT<T1,T2>:
判断T1和T2是否是类型相同
2. IsBaseType<T>:
Base Type是指T去掉一个指针,或者引用,或者数组,或者常量修饰符后用于构造T的类型.
如果T为基本类型,这IsBaseType<T>::eYes为1否则为0
3.IsFunctionT<T>:
IsFunctionT用于判断T是否是函数指针类型.
基本原理:数组元素不能为void,引用或者函数类型.
4.IsSuperT<Super,B>:
此函数用于判断Super是否是B的超类型.
Super是B的超类型是指C可以使用B用指针,引用,数组,const等通过有限次构造出来
5.TypeReplace<C,A,B>
接受一个复合类型C作为第一个参数,并将其中的类型A替换为类型B
6. TypeReplace4Func.hxx: 对函数类型进行特化,用于替换函数中的参数
7. TypeReplace4MemPtr.hxx:对成员指针(包括数据成员指针和成员函数指针)进行特化
8.TypeReplace4Templ.hxx: 对模板类进行特化
main.cpp: 测试代码
输出:
或许大家对第三个和第四个的输出有疑问,觉得上面的代码不能正确处理引用和const的情况
事实上代码是完全正确的,只是输出有点问题,这是因为在VC中输出typeid(DataType).name的时候,DataType中包含的const和&是不输出的,如果你不信不妨可以用VS2005试一下输出 cout<<typeid( int const &).name()<<endl; 你一定会为为这代码居然是输出int而大跌眼镜
补充:
对于不定参数的函数,本文就暂时不给1个参数以上的实现了,但是对于这个很容易扩充
以下是对于 Type Func(...)类型的不定参数的实现,其它实现请使用copy/paste功能
template<typename C, typename A, typename B> struct type_replace; //接受一个复合类型C作为第一个参数,并将其中的类型A替换为类型B typedef type_replace< void*, void, int > :: result_type t1; // int* typedef type_replace< int const* [10], int const, long > :: result_type t2; // long* [10] typedef type_replace< char& (*)(char&, const char*), char&, long > :: result_type t3;// long (*)(long, const char*)
定义:
1. IsSameT<T1,T2>:
判断T1和T2是否是类型相同
//IsSameT.hxx #pragma once template<typename T1,typename T2> struct IsSameT { enum { eYes = 0 }; }; template<typename T> struct IsSameT<T,T> { enum { eYes = 1 }; };
2. IsBaseType<T>:
Base Type是指T去掉一个指针,或者引用,或者数组,或者常量修饰符后用于构造T的类型.
如果T为基本类型,这IsBaseType<T>::eYes为1否则为0
//IsBaseT.hxx #pragma once template<typename T> struct IsBaseT { typedef T T_base_type; enum{ eYes = true}; }; /***********************************************************/ template<typename T> struct IsBaseT<T*> { typedef T T_base_type; enum{ eYes = false}; }; template<typename T> struct IsBaseT<T&> { typedef T T_base_type; enum{ eYes = false}; }; template<typename T> struct IsBaseT<T const> { typedef T T_base_type; enum{ eYes = false}; }; template<typename T> struct IsBaseT<T volatile> { typedef T T_base_type; enum{ eYes = false}; }; template<typename T> struct IsBaseT<T const volatile> { typedef T T_base_type; enum{ eYes = false}; }; template<typename T,int SIZE> struct IsBaseT<T [SIZE]> { typedef T T_base_type; enum{ eYes = false}; }; template<typename T> struct IsBaseT<T []> { typedef T T_base_type; enum{ eYes = false}; };
3.IsFunctionT<T>:
IsFunctionT用于判断T是否是函数指针类型.
基本原理:数组元素不能为void,引用或者函数类型.
//IsFunctionT.hxx #pragma once template<typename T> struct IsFunctionT { private: typedef char One; typedef struct { char a[2]; } Two; template<typename U> static One Test(...); template<typename U> static Two Test(U (*)[1]); template<typename U> static Two Test(int C::*); //抽象类 public: enum { eYes = sizeof(Test<T>(0)) == 1 }; }; template<typename T> struct IsFunctionT<T&> {enum { Yes = 0 }; }; template<> struct IsFunctionT<void> { enum{ eYes = 0 }; }; template<> struct IsFunctionT<void const>{ enum{ eYes = 0 }; };
4.IsSuperT<Super,B>:
此函数用于判断Super是否是B的超类型.
Super是B的超类型是指C可以使用B用指针,引用,数组,const等通过有限次构造出来
//IsSuperT.hxx #pragma once #include "IsBaseT.hxx" template<typename Super,typename B,int> struct IsSuperTWrapper; template<typename Super,typename B> struct IsSuperT { enum{ eYes = IsSuperTWrapper<Super, B ,IsBaseT<Super>::eYes>::eYes}; }; /******************************************************************/ template<typename Super,typename B,int> struct IsSuperTWrapper { typedef typename IsBaseT<Super>::T_base_type T_base_type; enum{ eYes =IsSuperTWrapper< T_base_type,B,IsBaseT<T_base_type>::eYes >::eYes}; }; template<typename Super,typename B> struct IsSuperTWrapper<Super,B,1> { enum{ eYes = 0}; }; template<typename Super> struct IsSuperTWrapper<Super,Super,1> { enum{ eYes = 1}; }; template<typename Super> struct IsSuperTWrapper<Super,Super,0> { enum{ eYes = 1}; }; template<typename Super,typename B> struct IsSuperTWrapper<Super const volatile,B const,0> { enum {eYes = 1}; }; template<typename Super,typename B> struct IsSuperTWrapper<Super const volatile,B volatile,0> { enum {eYes = 1}; };
5.TypeReplace<C,A,B>
接受一个复合类型C作为第一个参数,并将其中的类型A替换为类型B
//TypeReplace.hxx #pragma once #include "IsSuperT.hxx" #include "IsFunctionT.hxx" #include "IsSameT.hxx" template<typename C, typename A, typename B,int _Is_SuperT> struct TypeReplaceWrapper; template<typename C, typename A, typename B> struct TypeReplace { typedef typename TypeReplaceWrapper<C,A,B,IsSuperT<C,A>::eYes>::result_type result_type; }; /********************** C是A的超类的情况 Begin******************************************/ template<typename C, typename A, typename B,int SameT> struct SuperTypeReplaceWrapper; template<typename C, typename A, typename B> struct TypeReplaceWrapper<C,A,B,1> { typedef typename SuperTypeReplaceWrapper<C,A,B,IsSameT<C,A>::eYes>::result_type result_type; }; #define SUPER_TYPE_REPLACE_WRAPPER(exp) / template<typename C, typename A, typename B> / struct SuperTypeReplaceWrapper<C exp,A,B,0> / { / typedef typename SuperTypeReplaceWrapper<C,A,B,IsSameT<C,A>::eYes>::result_type exp result_type;/ } SUPER_TYPE_REPLACE_WRAPPER(*); SUPER_TYPE_REPLACE_WRAPPER(&); SUPER_TYPE_REPLACE_WRAPPER(const); SUPER_TYPE_REPLACE_WRAPPER(volatile); SUPER_TYPE_REPLACE_WRAPPER(const volatile); //数组 template<typename C, typename A, typename B,int SIZE> struct SuperTypeReplaceWrapper<C [SIZE],A,B,0> { typedef typename SuperTypeReplaceWrapper<C,A,B,IsSameT<C,A>::eYes>::result_type (result_type) [SIZE] ; }; //空数组 template<typename C, typename A, typename B> struct SuperTypeReplaceWrapper<C [],A,B,0> { typedef typename SuperTypeReplaceWrapper<C,A,B,IsSameT<C,A>::eYes>::result_type(result_type) [] ; }; //结束条件: C跟A的类型相同 template<typename A, typename B> struct SuperTypeReplaceWrapper<A,A,B,1> { typedef B result_type; }; template<typename C,typename A, typename B> struct SuperTypeReplaceWrapper<C const volatile,A const,B,0> { typedef B volatile result_type; }; template<typename C,typename A, typename B> struct SuperTypeReplaceWrapper<C const volatile,A volatile,B,0> { typedef B const result_type; }; /********************** C不是A的超类的情况 Begin******************************************/ #define NOSUPER_TYPE_REPLACE_WRAPPER(exp) / template<typename C, typename A, typename B> / struct TypeReplaceWrapper<C exp,A,B,0> / { / typedef typename TypeReplaceWrapper<C,A,B,0>::result_type exp result_type; / } NOSUPER_TYPE_REPLACE_WRAPPER(*); //指针特化 NOSUPER_TYPE_REPLACE_WRAPPER(&); //引用特化 NOSUPER_TYPE_REPLACE_WRAPPER(const); //const特化 NOSUPER_TYPE_REPLACE_WRAPPER(volatile); //const特化 NOSUPER_TYPE_REPLACE_WRAPPER(volatile const); //const特化 //数组特化 template<typename C, typename A, typename B,int SIZE> struct TypeReplaceWrapper<C [SIZE],A,B,0> { typedef typename TypeReplaceWrapper<C,A,B,0>::result_type (result_type)[SIZE]; }; //空数组特化 template<typename C, typename A, typename B> struct TypeReplaceWrapper<C[] ,A,B,0> { typedef typename TypeReplaceWrapper<C,A,B,0>::result_type (result_type)[]; }; template<typename C, typename A, typename B> struct TypeReplaceWrapper<C,A,B,0> { typedef C result_type; }; #define RESUALT_TYPE_DEF(exp) typedef typename TypeReplace< exp ,A,B>::result_type T_##exp #include "TypeReplace4Func.hxx" #include "TypeReplace4MemPtr.hxx" #include "TypeReplace4Templ.hxx" /********************** C不是A的超类的情况 End******************************************/
6. TypeReplace4Func.hxx: 对函数类型进行特化,用于替换函数中的参数
//TypeReplace4Func.hxx #pragma once template<typename C, typename A, typename B,int _Is_SuperT> struct TypeReplaceWrapper; //对于函数类型 //0参数 template<typename A, typename B,typename ResType> struct TypeReplaceWrapper< ResType (),A,B,0> { RESUALT_TYPE_DEF(ResType); typedef T_ResType (result_type)(); }; //1参数 template<typename A, typename B,typename ResType,typename T1> struct TypeReplaceWrapper< ResType (T1),A,B,0> { RESUALT_TYPE_DEF(ResType); RESUALT_TYPE_DEF(T1); typedef T_ResType (result_type)(T_T1); }; //2参数 template<typename A, typename B,typename ResType,typename T1,typename T2> struct TypeReplaceWrapper< ResType (T1,T2),A,B,0> { RESUALT_TYPE_DEF(ResType); RESUALT_TYPE_DEF(T1); RESUALT_TYPE_DEF(T2); typedef T_ResType (result_type)(T_T1,T_T2); }; //3参数 template<typename A, typename B,typename ResType,typename T1,typename T2, typename T3> struct TypeReplaceWrapper< ResType (T1,T2,T3),A,B,0> { RESUALT_TYPE_DEF(ResType); RESUALT_TYPE_DEF(T1); RESUALT_TYPE_DEF(T2); RESUALT_TYPE_DEF(T3); typedef T_ResType (result_type)(T_T1,T_T2,T_T3); }; //4参数 template<typename A, typename B,typename ResType,typename T1,typename T2, typename T3,typename T4> struct TypeReplaceWrapper< ResType (T1,T2,T3,T4),A,B,0> { RESUALT_TYPE_DEF(ResType); RESUALT_TYPE_DEF(T1); RESUALT_TYPE_DEF(T2); RESUALT_TYPE_DEF(T3); RESUALT_TYPE_DEF(T4); typedef T_ResType (result_type)(T_T1,T_T2,T_T3,T_T4); };
7. TypeReplace4MemPtr.hxx:对成员指针(包括数据成员指针和成员函数指针)进行特化
//TypeReplace4MemPtr.hxx #pragma once template<typename C, typename A, typename B,int _Is_SuperT> struct TypeReplaceWrapper; //数据成员指针类型特化 template<typename Class, typename A, typename B,typename DataType> struct TypeReplaceWrapper<DataType Class::*,A,B,0> { RESUALT_TYPE_DEF(Class); RESUALT_TYPE_DEF(DataType); typedef T_DataType (T_Class::*result_type); }; //成员函数类型,0参数 template<typename Class,typename A, typename B, typename ResType> struct TypeReplaceWrapper< ResType (Class::*)(),A,B,0> { RESUALT_TYPE_DEF(Class); RESUALT_TYPE_DEF(ResType); typedef T_ResType (T_Class::*result_type)(); }; //成员函数类型,1参数 template<typename Class,typename A, typename B, typename ResType,typename T1> struct TypeReplaceWrapper< ResType (Class::*)(T1),A,B,0> { RESUALT_TYPE_DEF(Class); RESUALT_TYPE_DEF(ResType); RESUALT_TYPE_DEF(T1); typedef T_ResType (T_Class::*result_type)(T_T1); }; //成员函数类型,2参数 template<typename Class,typename A, typename B, typename ResType,typename T1,typename T2> struct TypeReplaceWrapper< ResType (Class::*)(T1,T2),A,B,0> { RESUALT_TYPE_DEF(Class); RESUALT_TYPE_DEF(ResType); RESUALT_TYPE_DEF(T1); RESUALT_TYPE_DEF(T2); typedef T_ResType (T_Class::*result_type)(T_T1,T_T2); }; //成员函数类型,3参数 template<typename Class,typename A, typename B, typename ResType,typename T1,typename T2,typename T3> struct TypeReplaceWrapper< ResType (Class::*)(T1,T2,T3),A,B,0> { RESUALT_TYPE_DEF(Class); RESUALT_TYPE_DEF(ResType); RESUALT_TYPE_DEF(T1); RESUALT_TYPE_DEF(T2); RESUALT_TYPE_DEF(T3); typedef T_ResType (T_Class::*result_type)(T_T1,T_T2,T_T3); }; //成员函数类型,4参数 template<typename Class,typename A, typename B, typename ResType,typename T1,typename T2,typename T3,typename T4> struct TypeReplaceWrapper< ResType (Class::*)(T1,T2,T3,T4),A,B,0> { RESUALT_TYPE_DEF(Class); RESUALT_TYPE_DEF(ResType); RESUALT_TYPE_DEF(T1); RESUALT_TYPE_DEF(T2); RESUALT_TYPE_DEF(T3); RESUALT_TYPE_DEF(T4); typedef T_ResType (T_Class::*result_type)(T_T1,T_T2,T_T3,T_T4); };
8.TypeReplace4Templ.hxx: 对模板类进行特化
//TypeReplace4Templ.hxx #pragma once template<typename C, typename A, typename B,int _Is_SuperT> struct TypeReplaceWrapper; template<template <typename> class Class,typename A, typename B,typename T1> struct TypeReplaceWrapper<Class<T1> ,A,B,0> { RESUALT_TYPE_DEF(T1); typedef Class<T_T1> result_type; }; template<template <typename,typename> class Class,typename A, typename B,typename T1,typename T2> struct TypeReplaceWrapper<Class<T1,T2> ,A,B,0> { RESUALT_TYPE_DEF(T1); RESUALT_TYPE_DEF(T2); typedef Class<T_T1,T_T2> result_type; }; template<template <typename,typename,typename> class Class,typename A, typename B,typename T1,typename T2,typename T3> struct TypeReplaceWrapper<Class<T1,T2,T3> ,A,B,0> { RESUALT_TYPE_DEF(T1); RESUALT_TYPE_DEF(T2); RESUALT_TYPE_DEF(T3); typedef Class<T_T1,T_T2,T_T3> result_type; }; template<template <typename,typename,typename,typename> class Class,typename A, typename B,typename T1,typename T2,typename T3,typename T4> struct TypeReplaceWrapper<Class<T1,T2,T3,T4> ,A,B,0> { RESUALT_TYPE_DEF(T1); RESUALT_TYPE_DEF(T2); RESUALT_TYPE_DEF(T3); RESUALT_TYPE_DEF(T4); typedef Class<T_T1,T_T2,T_T3,T_T4> result_type; };
main.cpp: 测试代码
// Main.cpp : Defines the entry point for the console application. // #include <iostream> #include <typeinfo> #include <vector> using namespace std; #include "typereplace.hxx" #include "TypeReplace4Templ.hxx" class Test { }; class Test1 { }; int main(int argc, char* argv[]) { //普通类型 cout<<typeid( TypeReplace<int***,int**,long>::result_type).name()<<endl; cout<<typeid( TypeReplace<int***,int*****,long>::result_type).name()<<endl; cout<<typeid( TypeReplace<int &,int,long>::result_type).name()<<endl; cout<<typeid( TypeReplace<Test*****,Test**,long>::result_type).name()<<endl; //数据成员类型 cout<<typeid( TypeReplace<int ** Test::*,Test,Test1>::result_type).name()<<endl; cout<<typeid( TypeReplace<int ** Test::*,int,Test1>::result_type).name()<<endl; //成员函数类型 cout<<typeid( TypeReplace<int ** (Test::*)(int*******,int),int**, long>::result_type).name()<<endl; cout<<typeid( TypeReplace<int ** (Test::*)(int*******,int),Test, Test1>::result_type).name()<<endl; //函数类型 cout<<typeid( TypeReplace<int ** (int*******,int),int**, long>::result_type).name()<<endl; cout<<typeid( TypeReplace<void (int*******,int),int, long>::result_type).name()<<endl; //函数作为参数 cout<<typeid( TypeReplace<int ** (int*******,int(int***)),int**, long>::result_type).name()<<endl; //数组以及空数组 cout<<typeid( TypeReplace<int[],int**, long>::result_type).name()<<endl; cout<<typeid( TypeReplace<int**[],int**, long>::result_type).name()<<endl; cout<<typeid( TypeReplace<int[1000],int**, long>::result_type).name()<<endl; cout<<typeid( TypeReplace<int**[1000],int**, long>::result_type).name()<<endl; //模板类 cout<<typeid( TypeReplace<auto_ptr<int****>, int** ,long>::result_type).name()<<endl; return 0; }
输出:
long * int * * * long long * * * int * * Test1::* class Test1 * * Test::* long (__thiscall Test::*)(long * * * * *,int) int * * (__thiscall Test1::*)(int * * * * * * *,int) long __cdecl(long * * * * *,int) void __cdecl(long * * * * * * *,long) long __cdecl(long * * * * *,int (__cdecl*)(long *)) int [0] long [0] int [1000] long [1000] class std::auto_ptr<long * *> 请按任意键继续. . .
或许大家对第三个和第四个的输出有疑问,觉得上面的代码不能正确处理引用和const的情况
事实上代码是完全正确的,只是输出有点问题,这是因为在VC中输出typeid(DataType).name的时候,DataType中包含的const和&是不输出的,如果你不信不妨可以用VS2005试一下输出 cout<<typeid( int const &).name()<<endl; 你一定会为为这代码居然是输出int而大跌眼镜
补充:
对于不定参数的函数,本文就暂时不给1个参数以上的实现了,但是对于这个很容易扩充
以下是对于 Type Func(...)类型的不定参数的实现,其它实现请使用copy/paste功能
//0参数,不定参数,对于其它版本的不定参数暂时不给实现 template<typename A, typename B,typename ResType> struct TypeReplaceWrapper< ResType (...),A,B,0> { RESUALT_TYPE_DEF(ResType); typedef T_ResType (result_type)(); };
相关文章推荐
- 3.一个斐波那契数列是由数字1、1、2、3、5、8、13、21、34等等组成的,其中每一个数字(从第三个数字起)都是前两个数字的和。创建一个方法,接受一个整数参数,并显示从第一个元素开始总共由该参数
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- Mysql循环游标作为其中一个参数插入到另一个表
- 命令替换符(一个命令的输出作为另一个命令的参数)
- 创建一个包,其中定义一个过程,可以查询得到编号为7900的员工的姓名ename、薪水sal、佣金comm、上司编号mgr (通过OUT类型的参数将结果返回并打印) (注意包有包头部分的声明和包体部分的
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- 模板元编程时的参数推导类型输出
- 4.构造方法与重载:定义一个网络用户类,要处理的信息有用户 ID、用户密码、 email 地址。在建立类的实例时把以上三个信息都作为构造函数的参数输入, 其中用户 ID 和用户密码时必须缺省时 ema
- 接受一个整型作为参数, 返回它所有约数的列表,包括1和本身
- 将一个文件的输出作为grep第一个参数的输入
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- 编写一个函数,接受三个string参数,s,oldVal和newVal。使用迭代器及insert和erase函数将s中所有oldVal替换为newVal。测试你的程序,用他替换通用的简写形式,如,将“tho”,将“”“”
- 用C语言编写函数实现一个整数计算机,程序接受三个参数,第一个参数为操作项,后两个参数为操作数。
- 关于printf()与scanf()在不同情形下可以接受不同类型的参数的一个例子。
- 实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。 例如:输入t
- 接受一个整型作为参数,返回该整数所有素数因子的列表
- node 的express 如何接受以一个网站的url作为参数的路由
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- C# 001 --- 正确的删除一个控件的事件函数 --- 解决错误: “A”不包含“B”的定义,并且找不到可接受类型为“A”的第一个参数的扩展方法“B”(是否缺少 using 指令或程序集引用?)
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。