当前位置:首页 > CN2资讯 > 正文内容

我的世界java粘贴指令

4天前CN2资讯


TypeList固然精妙,但是就像链表相对数组有其不足一样,TypeList中的类型递归定义使得取得其中某个类型会变成比较麻烦的事,从而也把算法的复杂性提高了,或许这些都还能忍受,比较Loki::TypeList提供了足够的算法供我们使用,但是TypeList的一个致命弱点却在我编写通讯兵模式时候发现了。

 

4.1 TypeList的不足

当我的程序需要记录某个函数的参数类型时候我们用到TypeList很方便,

例如下面的程序:

template<typename class DoSomeThing { typedef typedef typedef public: void void void void };

    我们可以用不同类型特化DoSomeThing以后根据参数个数不同调用成员函数Do的重载体,这个技法在我后面的程序中将会出现很多,这就可以让我们在特化DoSomeThing之前不用知道具体会有几个参数或者会是什么类型,这就达到了泛化的目的。

    但是问题出来了,如果我们需要Do的重载体接收的参数类型不是一个单数据类型,而是需要接收一个TypeList容器的时候,TypeList似乎就开始无能为力了,因为我们虽然可以写出类型这样的代码

typedefint,unsigned int) IntType; typedefchar,unsigned char) CharType; typedef TYPELIST_2(IntType,CharType) SomeType;

但是我们却不能用TypeAt提取出SomeType中的IntType,如果我们用下面的代码得到的结果将不是我预期的:

TypeAt<SomeType,0>::Result

我们也许希望得到一个IntType,但是程序会返回一个int给我们,这是因为TypeList类似链表的递归定义会把SomeType展开成

TYPELIST_4(int,unsigned int, char,unsigned char)

对上面这个TypeList求取第一个类型当然就是int。这曾经把我弄得哭笑不得,或许自己再写一些代码把其中的IntType封装一下再存入进去能解决问题,但是为此我花费了若干天时间研究该怎么写这个封装代码,而且越到后面越是被其复杂的递归弄得晕头转向。

于是我一不做二不休,直接抛弃TypeList,自己设计了TypeVector。

 

4.2 一个似曾相识却又崭新的世界

为了让TypeVector能存储其自身,我必须想办法抛弃递归定义的技法,由此

我想到了下面的代码:

//这里我们只设置了7个类型,你可以写更多,但是在我后面的程序用不了那么多 template< typename Type0 = NullType,typename typenametypename typenametypename typename Type6 = NullType > struct TypeVector { typedef typedef typedef typedef typedef typedef typedef };

       TypeVector的形态和TypeList形成了鲜明对比,TypeVector更为简洁,而且最重要的是不需递归就可以直接从中取出任意一个类型。这个形态很像数组的定义,不过不一样的是它是用来存储类型的。

 

4.3 TypeVector的算法

当我实作出TypeVector之前完全没有想到会有如此大的收获,因为我仅仅是

能存储其自身而创作的它,可是我却发现其算法是如此简洁明了,和TypeList形成了鲜明对比,在定制算法时候很多都是复制粘贴的操作,虽然代码量看似很多,但是你肯定不用花很多时间在调试代码的正确性上。

       为了能兼容使用TypeList的程序,我采用了和TypeList同样的算法命名。

 

4.3.1 求取TypeVector长度

现在求取TypeVector的长度变得异常简单,只是一些模板的偏特化而已,一

眼就可看懂其算法思想。

//******************************************************************** //名称: Length //作用: 求取TypeVector中类型个数 //输入(模板参数): TVector,需要求取长度的TypeVector。 //输出: Length<TVector>::value 求取长度值 //算法思想: // 根据TypeVector的特化方式判断出其类型个数。 //******************************************************************** template<typename TVector> struct template<> struct Length<TypeVector<> > { enum }; template<typename struct Length<TypeVector<T0> > { enum }; template<typename T0,typename struct Length<TypeVector<T0,T1> > { enum }; template<typename T0,typename T1,typename struct Length<TypeVector<T0,T1,T2> > { enum }; template<typename T0,typename T1,typename T2,typename struct Length<TypeVector<T0,T1,T2,T3> > { enum }; template<typename T0,typename T1,typename T2,typename T3,typename struct Length<TypeVector<T0,T1,T2,T3,T4> > { enum }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename struct Length<TypeVector<T0,T1,T2,T3,T4,T5> > { enum }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct Length<TypeVector<T0,T1,T2,T3,T4,T5,T6> > { enum };

 

使用时候也是和TypeList一样的使用方法:

Length< TypeVector<int,unsigned int, char,unsigned char> >::value;

4.3.2 求TypeVector某个索引值处的类型

其实由于TypeVector类似数组的结构,我们可以很轻易的写出下面这个码:

typedefint,unsigned int,long int> IntType;

当我们要取用里面索引值第1个型别时候可以这样写:

typedef IntType::Type1 MyType;

    不过为了兼容TypeList的程序,我们还是要提供同样的接口,哪怕看似无用的。不过即便是这样,还是能从中学到一些神奇的技巧,请你别跳过这,耐心往下看。

//******************************************************************** //名称: TypeAt //作用: 求取TypeVector中某索引值处的类型 //输入(模板参数): TVector,需要求取的TypeVector;i,索引值。 //输出: TypeAt<TVector,i>::Result 求取长度值 //算法思想: // 根据i数值不同做出不同的偏特化体 //******************************************************************** templatetypename TVector , unsigned int struct TypeAt { typedef }; templatetypename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct TypeAt<TypeVector<T0,T1,T2,T3,T4,T5,T6>,0> { typedef }; templatetypename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct TypeAt<TypeVector<T0,T1,T2,T3,T4,T5,T6>,1> { typedef }; templatetypename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct TypeAt<TypeVector<T0,T1,T2,T3,T4,T5,T6>,2> { typedef }; templatetypename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct TypeAt<TypeVector<T0,T1,T2,T3,T4,T5,T6>,3> { typedef }; templatetypename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct TypeAt<TypeVector<T0,T1,T2,T3,T4,T5,T6>,4> { typedef }; templatetypename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct TypeAt<TypeVector<T0,T1,T2,T3,T4,T5,T6>,5> { typedef }; templatetypename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct TypeAt<TypeVector<T0,T1,T2,T3,T4,T5,T6>,6> { typedef };

    写完上面的代码以后我本没太多想法,后又得到网上一位前辈(网名Intercessor)提示发现其实一切都可以变得更酷,利用宏定义在编译期执行的动作,可以简化很多重复的代码。简化后的代码像这样:

//给一个宏定义,用##(连接符)连接序号,最后就可以做出所有偏特化体 #define template <typename T0,typename T1,typename ,typename T3,typename T4,typename T5,typename T6> / struct / { / typedef T##atPos Result; / }; templatetypename TVector , unsigned int struct TypeAt { typedef }; //后面就可以利用宏定义写出重复的代码。 META_TYPEAT(0) META_TYPEAT(1) META_TYPEAT(2) META_TYPEAT(3) META_TYPEAT(4) META_TYPEAT(5) META_TYPEAT(6)

 

当我们需要查找某个索引值处的类型时候,程序是这样的。

 

typedefint,unsigned int,long int> IntType; typedef TypeAt<IntType,1>::Result MyType;

4.3.3 向TypeVector末端添加类型

类似前面的算法,向末端添加一个类型就相当于重新定义一个TypeVector并

返回,主要技巧还是模板的偏特化,下面给出代码:

//******************************************************************** //名称: Append //作用: 向TypeVector末端添加类型 //输入(模板参数): TVector,需要添加的TypeVector;T,添加类型。 //输出: Append<TVector,T>::Result 添加后得到的TypeVector //算法思想: // 根据TypeVector长度不同做出不同的偏特化体 //******************************************************************** template<typename TVector, typename T> struct template<typename struct Append<TypeVector<>,T> { typedef }; template<typename T0,typename struct Append<TypeVector<T0>,T> { typedef }; template<typename T0,typename T1,typename struct Append<TypeVector<T0,T1>,T> { typedef }; template<typename T0,typename T1,typename T2,typename struct Append<TypeVector<T0,T1,T2>,T> { typedef }; template<typename T0,typename T1,typename T2,typename T3,typename struct Append<TypeVector<T0,T1,T2,T3>,T> { typedef }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename struct Append<TypeVector<T0,T1,T2,T3,T4>,T> { typedef }; template<typename T0,typename T1,typename T2, typename T3,typename T4,typename T5,typename struct Append<TypeVector<T0,T1,T2,T3,T4,T5>,T> { typedef };

    当需要向一个TypeList末尾添加一个类型的时候代码像这样:

typedef Append< TypeVector< int,unsigned int > ,long int >::Result IntType;

4.3.4 删除TypeVector中某索引值所在位置的类型

之所以先介绍这个删除算法是因为另外一个删除算法(删除第一次匹配

类型)需要依赖到这个算法

    这个算法同样很简单,只需要一些模板面特化技术就能实现。

//******************************************************************** //名称: ErasePose //作用: 删除TypeVector中某索引值所在类型 //输入(模板参数): TVector,需要添加的TypeVector;i,索引值。 //输出: ErasePose<TVector,i>::Result 删除后的TypeVector //算法思想: // 根据索引值i不同做出不同的偏特化体 //******************************************************************** templatetypename TVector , int struct ErasePose { typedef }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct ErasePose<TypeVector<T0,T1,T2,T3,T4,T5,T6>,0> { typedef }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct ErasePose<TypeVector<T0,T1,T2,T3,T4,T5,T6>,1> { typedef }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct ErasePose<TypeVector<T0,T1,T2,T3,T4,T5,T6>,2> { typedef }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct ErasePose<TypeVector<T0,T1,T2,T3,T4,T5,T6>,3> { typedef }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct ErasePose<TypeVector<T0,T1,T2,T3,T4,T5,T6>,4> { typedef }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct ErasePose<TypeVector<T0,T1,T2,T3,T4,T5,T6>,5> { typedef }; template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename struct ErasePose<TypeVector<T0,T1,T2,T3,T4,T5,T6>,6> { typedef };

    用法如下代码:

typedef ErasePose< IntType,1 >::Result E1IntType;

 

4.3.5 得第一个匹配TypeVector中某类型的索引值

按照我们预先的希望,或者惯性思考,这个算法的代码也应该是若干重复的

模板偏特化而已,但是当实作出代码以后才发现原来没有那么简单,也许你会想到这个算法的代码类似这样:

template<typename TVector , typename struct IndexOf { enum }; template<typename struct IndexOf<TypeVector<T>,T> { enum }; template<typename T0,typename struct IndexOf<TypeVector<T0,T>,T> { enum }; //...and more...

如果是这样,那当我写出这样的代码时候,将会出现错误结果。

typedefint,char,int,double> SomeType; intint>::value;

    编译器看到上面代码将会提示你,它无法判断该执行哪一个模板偏特化体,因为索引0位置和索引2位置的偏特化体都有条件得到执行(偏特化与你书写的先后顺序无关),这就是所谓的模绫两可。

    为了解决这个问题,我们只有能回到该死的偏特化递归去了,不过幸运的是毕竟不是每个算法都必须涉及到递归,否则我们这个TypeVector就没太多存在意义了。

    下面介绍正确的IndexOf算法

//******************************************************************** //名称: IndexOf //作用: 在TypeVector中查找第一个匹配某一类型的索引值 //输入(模板参数): TVector,需要查找的TypeVector;T,所要查找的类型 //输出: IndexOf<TVector,T>::value 查找后得到的索引值 //算法思想: // 如果TVector为空,则定义value为-1 // 否则 // 如果TVector第一个类型匹配T,则定义value为0 // 否则 // 删除TypeVector的第一个类型再做索引,并且把结果value赋值临时变// 量temp。 // 如果temp为-1,则定义value为-1, // 否则 // 定义value为 temp + 1 。 //******************************************************************** templatetypename TVector , typename T> struct template<typename struct IndexOf<TypeVector<> ,T> { enum }; templatetypename structtypename { enum{ value = 0 }; }; templatetypename TVector ,typename struct IndexOf { private: enum{ temp = IndexOf<typename public: enum{ value = temp == -1 ? -1 : 1 + temp }; };

如果你需要索引某类型时候,程序代码像这样的:

typedefint,char,int,double> SomeType; intint>::value;

上面的index将得到0;

 

4.3.6 删除TypeVector中第一个匹配的类型

这个算法之所以在最后讲是因为需要用到前面算法的帮助,否则又将是让人

厌烦的模板偏特化递归调用。

//******************************************************************** //名称: Erase //作用: 删除TypeVector中查找第一个匹配的某类型 //输入(模板参数): TVector,需要删除的TypeVector;T,所要删除的类型 //输出: Erase<TVector,T>::Result 删除后得到的TypeVector //算法思想: // 求出类型T的索引位置并赋值value,然后删除value索引所在位置的类型。 //******************************************************************** template<typename TVector,typename struct Erase { enum typedef typename };

 

4.4 TypeVector结束语


TypeVector相信大家现在有所了解了,其以类似数组方式的存储形态使得其

支持随即读取其中某个类型,这在很大程度上简化了我们对应算法的复杂程度,而且其有一个优良的特性就是可以将TypeVector类型存储于TypeVector中,且最后可以调用IndexOf寻找出其索引值或者根据索引值调用TypeAt获得其类型,这在某些复杂类型情况下是很方便的。

    但是正所谓寸有所短,尺有所长。TypeVector相对于TypeList的缺点就是维护稍显困难,当我们因为程序需要而在库文件中扩展TypeList的长度时候我们并不需要修改其算法,但是如果我们修改TypeVector最大容量以后就必须修改其对应算法,不过值得高兴的是我们可能只需要一些复制粘贴动作就可以修改了,但是即便最小的修改也需要重新编译程序,这在某些时候显得异常麻烦。

    再好的算法也必须在最适合的环境下才能得到最大的效率,这也就是我同时介绍TypeList和TypeVector的关系,因为不一定其中一种就是最好的,只是看在什么环境下了。

    你可能想看:

    扫描二维码推送至手机访问。

    版权声明:本文由皇冠云发布,如需转载请注明出处。

    本文链接:https://www.idchg.com/info/21695.html

    分享给朋友:

    “我的世界java粘贴指令” 的相关文章

    中国电信CN2网络费用高吗?一张卡的价格及优势解析

    在如今这个高度互联的时代,稳定的网络连接已经成为不可或缺的重要需求。无论是商务人士出差在外,还是留学生在海外学习,亦或是企业需要在全球范围内进行数据传输,一张高速、稳定的网络卡都是必不可少的工具。而中国电信的CN2网络,作为国内知名运营商的拳头产品,凭借其覆盖范围广、速率快、稳定性强的特点,成为众多...

    远程VPS优选指南:高效管理虚拟专用服务器的最佳实践

    随着远程工作的普及和数字化转型的加速,远程VPS(虚拟专用服务器)逐渐成为许多企业和个人的首选工具。VPS通过虚拟化技术,让我们能够在一台物理服务器上同时运行多个独立的操作系统,这种灵活性使得用户能够像管理独立服务器那样,远程登录和管理自己的虚拟环境。每天都有更多的人意识到,拥有一个VPS可以为他们...

    深度解析韩国makemodel:传统与现代结合的时尚理念

    markdown格式的内容 韩国makemodel概念 谈到韩国makemodel,我首先感受到了它所传递的深厚文化底蕴。这一时尚理念融合了传统与现代,不仅仅是对衣物的设计,更是一种对韩国文化的致敬。它通过巧妙的配搭,将历史悠久的韩服元素与现代流行趋势相结合,创造出一种独特的美学风格。每一件作品都像...

    DirectAdmin安装全攻略:快速安装与配置指南

    DirectAdmin是一款由国外开发的虚拟主机管理系统。我第一次接触它时,就被其强大的功能和用户友好的界面所吸引。它不仅可以管理服务器,还能帮助我轻松设置EMAIL、DNS、FTP等。这种集中管理的方式大大提高了我的工作效率,尤其是对那些需要频繁处理服务器配置的用户来说,DirectAdmin无疑...

    BT下载机的使用技巧与软件下载推荐

    在数字时代,文件共享变得越来越普遍,BT下载机作为一种基于BitTorrent协议的P2P(Peer-to-Peer)文件共享工具,扮演着重要的角色。我记得第一次接触BT下载机时,发现它的操作不仅简单,还能快速下载大型文件,这让我对它产生了浓厚的兴趣。BT下载机允许用户通过种子文件(.torrent...

    如何优化网络体验:VPS中转全面指南

    我一直对如何使用技术来优化我的网络体验感到好奇。最近,我发现了VPS中转这种神奇的方法。简单来说,VPS中转就是利用一台虚拟私人服务器(VPS),将我的网络流量转发到另一个指定的网络地址。这种功能主要用于加速访问某些海外网站,帮助我突破网络限制以及保护我的上网隐私等。 在日常使用中,我会遇到一些网站...