- 浏览: 208491 次
- 性别:
- 来自: 重庆
-
文章分类
最新评论
TypeList
- 博客分类:
- c++
转自:http://blog.csdn.net/hhygcy/article/details/3339176
其他:http://blog.csdn.net/gxut555/article/details/7454329
假设你有若干个类,现在你希望给每个类分配一个唯一的ID。最简单的方法无非是手工的为这个类添加一个id,前提是你确信给这个类的id与其它类的id没有冲突,为此你需要查看其它所有类的代码。
稍微好一点的办法是使用GUID产生器产生的GUID,这样就可以保证每个类的id都是唯一的了。但是GUID128位的长度似乎又有一些浪费。
其实还有这样的一个思路:我们到一个地方将这些类进行注册,注册的同时返回一个数值作为类的id。那么用什么作为这些类进行注册的容器呢?
Loki库中的TypeList就是一个理想的选择。TypeList就象一个普通的List,但是它里面“存储”的是一个一个的Type,而不是具体的数据(其实TypeList是借助模板元编程实现的,所以在编译之后,TypeList也就不存在了,因此“存储”二字需要加上引号)。
我们可以将所有的类都添加到TypeList中,然后使用IndexOf返回每个类在TypeList中的索引,从而达到取得唯一ID的目的。
套用一个现在很流行的句式,(好多什么编程之美或者代码之美的)。我想看了第三章Modern C++ Design能感受的就是递归之美。而其中主要介绍的TypeList就是这样一个递归演绎的完美的例子。
其实TypeList本身的定义非常简单。就是一个有Head有Tail的一个简单的空的定义
template
struct Typelist
{
typedef T Head;
typedef U Tail;
};
但是如果加上一下这一组宏定义,这个原来的定义就可以无限延伸了
#define LOKI_TYPELIST_1(T1) ::Loki::Typelist
#define LOKI_TYPELIST_2(T1, T2) ::Loki::Typelist
#define LOKI_TYPELIST_3(T1, T2, T3) ::Loki::Typelist
当 然这里的Loki就是本书主要介绍的Loki Library.的名字空间。用过这样的递归的调用你就可以创建出类似的LOKI_TYPELIST_50甚至LOKI_TYPELIST_100。当让 可以让他变的更为强大,强大到随意的添加一个新的类,删除其中的一个类,或者删除冗余的重复。
我们从简单的来看先:
template struct Length;
template <> struct Length
{
enum { value = 0 };
};
template
struct Length<> >
{
enum { value = 1 + Length::value };
};
这 里的实现处处投射出递归的思想,Length这样的模板如何显示出value呢。如果TList是NullType的时候(NullType是这里定义的 一个表示空的类,前面章已有说明),那长度就是0,慢慢来, 如果这个TypeList是TypeList,可以看到value = 1 + Length::value,也就是1。 当然如果是LOKI_TYPELIST_x定义的类就返回LOKI_TYPELIST_(x-1)的长度加上1。这样的实现通过反复的去头操作实现。(就 是去掉TypeList中的T来实现)这样的操作后面还有非常多。
template struct TypeAt;
template
struct TypeAt, 0>
{
typedef Head Result;
};
template
struct TypeAt, i>
{
typedef typename TypeAt::Result Result;
};
TypeAt 这个模板用来提取出这个TypeList中某个Index对应的类,非常直观。类似的如果index是0,就返回当前这个TypeList的Head,就 是第一个类对应的类型。如果是非0的i呢?就和第一个定义一样,去掉Head以后,再找整个TypeList中从Tail第一项开始的第i-1个。递归, 还是递归。这样的定义随处可见。真很佩服Andrei Alexandrescu。天才,真是天才!随着看这本书的深入,越来越觉得自己的苍白,好像从来没有学会C++过。
继续来看写稍微复杂点的定义。
template struct IndexOf;
template
struct IndexOf
{
enum { value = -1 };
};
template
struct IndexOf, T>
{
enum { value = 0 };
};
template
struct IndexOf, T>
{
private:
enum { temp = IndexOf::value };
public:
enum { value = (temp == -1 ? -1 : 1 + temp) };
};
这 个定义乍一看还真有点迷糊, 不过仔细分析看看就明了了。慢慢分析,如果这个TypeList是空的话,那就返回-1,表示不包含这个T, 如果第一个就是T的话,那就返回0这样的index。这样的流程也符合一般的写递归的流程,先找到收敛条件,然后在逐次递归:) 如果第一个是Head,还不是T那怎么办呢,我们这个value就是取决与temp,而temp的取得呢是靠从Tail开始的这个list中的 value,如果在IndexOf中没有找到T,那value就是一个是-1,那TypeList的value也就是-1,因为没有。如果能找到那之前的 value至少是0开始的,就可以依次往上加1。现在看还挺清楚的了。
就是这样的一段段的定义可以定义出这么一大陀的东西:
template struct Length;
template struct TypeAt;
template struct IndexOf;
template struct Append;
template struct Erase;
template struct EraseAll;
template struct NoDuplicates;
template struct Replace;
template struct ReplaceAll;
template struct Reverse;
template struct MostDerived;
template struct DerivedToFront;
可是有了这些个定义有什么用呢??这是一个Good Question。这样的模式可以帮助我们毫不费力的创建出一些列的满足特定需求的类
template class Unit>
class GenScatterHierarchy;
// GenScatterHierarchy specialization: Typelist to Unit
template class Unit>
class GenScatterHierarchy, Unit>
: public GenScatterHierarchy
, public GenScatterHierarchy
{
public:
typedef Typelist TList;
typedef GenScatterHierarchy LeftBase;
typedef GenScatterHierarchy RightBase;
};
// Pass an atomic type (non-typelist) to Unit
template class Unit>
class GenScatterHierarchy : public Unit
{
typedef Unit LeftBase;
};
// Do nothing for NullType
template class Unit>
class GenScatterHierarchy
{
};
template
struct Holder
{
T value_;
};
typedef GenScatterHierarchy WidgetInfo;
就像书中给出的这个例子一样。GenScatterHierarchy的定义结合了TypeList的优势,一个简单的一定WidgetInfo就定义出了至少这些个类: Holder,Holder和Holder而且还有一定的继承关系, 显然他们WidgetInfo继承自他们。
所以这样的语句就很自然了
WidgetInfo obj;
string name = (static_cast&>(obj)).value_;
神奇吧。更厉害的是可以把GenScatterHierarchy这个分散的(scattered)继承关系变为线性的。那就是GenLinearHierarchy了,这个就不具体讲了,相信以后具体介绍Loki里面容器设计的时候还会设计到的。今天就到这里吧。
#include <stdio.h> struct NullType; template <typename T0 = NullType, typename T1 = NullType, typename T2 = NullType, typename T3 = NullType, typename T4 = NullType, typename T5 = NullType> struct typelist { typedef T0 Head; typedef typelist<T1, T2, T3, T4, T5> Tail; enum { length = 1 + Tail::length }; }; template <> struct typelist<NullType, NullType, NullType, NullType, NullType, NullType> { enum { length = 0 }; }; template <typename TL, int n, bool OutOfRange = (n >= TL::length)> struct type_at { typedef typename type_at<typename TL::Tail, n-1>::type type; }; template <typename TL> struct type_at<TL, 0, false> { typedef typename TL::Head type; }; template <typename TL, int n> struct type_at<TL, n, true> { }; template <typename T, typename U> struct is_same_type { enum { value = false }; }; template <typename T> struct is_same_type<T, T> { enum { value = true }; }; template <typename TL, typename T, int count = -1, bool equalsHead = is_same_type<typename TL::Head, T>::value> struct index_of { enum { value = 1 + index_of<typename TL::Tail, T, count-1>::value }; }; template <typename TL, typename T, int count> struct index_of<TL, T, count, true> { enum { value = 0 }; }; template <typename T, typename U, int count> struct index_of<typelist<T>, U, count, false> { enum { value = count }; }; template <typename T, typename U, bool greaterThan = (sizeof(T) >= sizeof(U))> struct type_selector { typedef T type; }; template <typename T, typename U> struct type_selector<T, U, false> { typedef U type; }; template <typename TL> struct largest_type { typedef typename type_selector<typename TL::Head, typename largest_type<typename TL::Tail>::type>::type type; }; template <typename T> struct largest_type<typelist<T> > { typedef T type; }; int main() { typedef typelist<int, float, double, char> types; printf("%d\n", types::length); type_at<types, 3>::type ch = 'c'; printf("%c\n", ch); printf("%d\n", index_of<types, unsigned>::value); printf("%d\n", index_of<types, double>::value); largest_type<types>::type d = 2.5; printf("%lf\n", d); printf("%d\n", index_of<types, largest_type<types>::type>::value); }
#include <stdio.h>
#include <typeinfo.h> // // TypeList // template <class T, class U> struct TypeList { typedef T Head; typedef U Tail; }; struct NullType { }; #define TYPELIST_1(T1) TypeList<T1, NullType> #define TYPELIST_2(T1, T2) TypeList<T1, TYPELIST_1(T2) > #define TYPELIST_3(T1, T2, T3) TypeList<T1, TYPELIST_2(T2,T3) > // // Length // template <class TList> struct Length; template <> struct Length<NullType > { enum {value = 0}; }; template <class T,class U> struct Length<TypeList<T,U> > { enum {value = 1 + Length<U>::value}; }; // // TypeAt // template <class TList, unsigned int index> struct TypeAt; template <class Head, class Tail> struct TypeAt< TypeList<Head,Tail>,0 > { typedef Head Result; }; template <class Head, class Tail, unsigned int index> struct TypeAt< TypeList<Head,Tail>,index > { typedef typename TypeAt<Tail, index-1>::Result Result; }; // // IndexOf // template <class TList, class T> struct IndexOf; template <class T> struct IndexOf< NullType, T > { enum {value = -1}; }; template <class T,class Tail> struct IndexOf< TypeList<T, Tail>, T > { enum {value = 0}; }; template <class Head,class Tail, class T> struct IndexOf< TypeList<Head, Tail>, T > { private: enum { temp = IndexOf<Tail,T>::value }; public: enum { value = temp==-1 ? -1 : 1 + temp}; }; // // Append // template <class TList, class T> struct Append; // // push_front // template <class TList, class T> struct push_front { typedef TypeList<T, > }; int main(int argc, char *argv[]) { printf("Hello, world\n"); typedef TYPELIST_3(int, float,char) MyTypeList; printf("MyTypeList length %d\n", Length<MyTypeList>::value); printf("MyTypeList TypeAt 0 %s\n", typeid(TypeAt<MyTypeList,0>::Result).name()); printf("MyTypeList IndexOf<int> %d\n", IndexOf<MyTypeList, float>::value); return 0; }
发表评论
-
C++的原子操作
2012-12-20 17:43 4697在多进程(线程)访问资源时,能够确保所有其他的进程(线程 ... -
匿名namespace的作用以及它与static的区别
2012-12-20 17:24 1865一。匿名namespace的作用 在C语言中,如果我们 ... -
C++类型萃取技术
2012-12-19 15:16 1158Traits技术可以用来获得一个 类型 的相关信息的。 ... -
数值压缩存储方法Varint
2012-12-19 14:35 881转自:http://www.cnblogs.com/smark ... -
template <unsigned int N>
2012-12-19 11:51 1508详见:http://stackoverflow.com/ ... -
二维指针*(void **)的研究(uC/OS-II案例)
2012-12-19 22:20 3308原文 : http://blog.csdn ... -
多级指针和链表
2012-12-18 22:28 0如果看到一个声明:t ... -
理解*(void**)b
2012-12-18 22:03 0#include <stdio.h> ... -
STL标准库:Allocator能做什么
2012-12-18 20:10 0The Standard Librarian: Wha ... -
三种的allocator实现源代码的对比
2012-12-18 19:55 1353转自:http://blog.csdn.net ... -
结构体内变量相对便宜与list_entry()宏
2012-12-18 17:59 963#define list_entry(ptr, t ... -
声明与函数、函数指针---(*(void (*)( ) )0)( ) 解析
2012-12-18 17:33 1123概述 在很 ... -
c++模板(类型依赖)说明例子
2012-12-18 16:57 1173#include <iostream> # ... -
C++中三种new的用法
2012-12-18 16:44 1845我评价自己的C++水平还未入门的确不够准确,应该是远远未 ... -
C++,永久改变你写异常安全代码的方式(神奇的Loki::ScopeGuard)
2012-12-17 20:19 2528作者:Andrei Alexandrescu and P ... -
C++的make_pair函数
2012-12-17 17:19 3538Pairs C++标准程序库中凡是“必须返回两 ... -
C++的explicit构造函数
2012-12-13 15:59 684按照默认规定,只有一个参数的构造函数也定义了一个隐式转换 ...
相关推荐
源码展示: #include using namespace std; template <typename> struct typelist; typedef typelist <int> defaultPolicys; template <typename> struct ... struct concat<typelist>, typelist<B> > { typ
2、新建TypeList.jsp页面 3、新建GoodsType的实体类 4、新建GoodsTypeDAO的操作类 5、在BusinessDelegate类中注册相应的方法 6、在TypeList.jsp页面中调用方法查询所有的类型 并且查询出的所有类型在做成链接时都要...
It can traverse one TypeList or enum value , then call user's template function by suitable type/enum value. This feature converts runtime data into compile data to meet metaprogramming requirement ...
javabean分页程序,适合初学jsp的朋友 <br>1、数据库表中有GoodsType表 2、新建TypeList.jsp页面 3、新建GoodsType的实体类 4、新建GoodsTypeDAO的操作类 5、在BusinessDelegate类中注册相应的方法...
微信小程序icon组件的实现,具体如下 ... typeList: ['success', 'success_no_circle', 'info', 'warn', 'waiting', 'cancel', 'download', 'search', 'clear'] }, }) 引入图标库 方法 微信小程序—-引入外部字体
- **4.1 TypeList 的不足**:TypeList 在某些场景下可能不够灵活。 - **4.2 一个似曾相识却又崭新的世界**:TypeVector 引入了更多的功能和改进。 - **4.3 TypeVector 的算法**: - **4.3.1 求取 TypeVector 长度**...
运行typelist.py对特征数据进行可视化展示。 data.zip中的2.xlsx为白名单和黑名单特征的整合。 运行SVM.py、forest_split.py、DNN.py机器学习训练和预测数据(其中DNN用到的是DNN的分类算法)。 基于传统机器学习...
typeList.Sort((Type type1, Type type2) => type1.FullName.CompareTo(type2.FullName)); foreach (Type type in typeList) { // Response.Write(type.Name.Replace("Controller", "") + " \n"); System....
FieldInfo[] fieldList = typeList[i].GetFields(BindingFlags.NonPublic | BindingFlags.Instance); for (int z = 0; z < fieldList.Length; z++) { // 进一步处理字段(示例代码省略) } } } // 返回成功...
# 基于C++98的嵌入式模板库项目 ## 项目简介 ... Typelist类型列表数据结构,可计算长度及判断类型包含关系。 TypeTraits提供类型特性功能,用于判断类型是否相同。 Pow2用于计算幂值的模板类。
要求:1、服务器环境:.Net2.0 + IIs 2、在/js/common.js中typeList参数可以修改题目类型以及抽题方式 3、web.config可以配置每种类型题目的数量 4、题库可以设置题目的分值 5、在/js/exam.js中可以设置考试时间之类...
type_list 另一个type_list实现(C ++ 17;仅允许将文字类型用作type_list元素;已测试:MSVC 2019 16.9.2,GNU g ++ 10.1.0,clang 10.0)
选择完毕后,软件会弹出另一个名为“Type List”的对话框。 在“Type List”对话框中,用户需选择“SST39VF088”,并点击“RUN”。点击之后,软件会弹出“Programmer Status”对话框,用户需继续点击“确定”来关闭...
case MDIbg_TypeList.File: // 从文件加载图片并绘制 using (Image img = Image.FromFile("path_to_image.png")) { g.DrawImage(img, 0, 0, this.Width, this.Height); } break; case MDIbg_TypeList.Draw: ...
flash type list,包含三星,intel.镁光
<s:List id="typeList" x="0" y="0" width="100%" height="100%" itemRenderer="com.sxzb.baseData.view.BaseTypeItemrender" dataProvider="{gm.baseTypeList}"> </s:List> ``` - `itemRenderer=...
The library makes extensive use of C++ template metaprogramming and implements several commonly used tools: typelist, functor, singleton, smart pointer, object factory, visitor and multimethods. ...
<% ArrayList typelist=(ArrayList)session.getAttribute("artTypeList"); %> 博客后台-发表文章 <tr><td colspan="2"></td></tr> <td valign="top"></td> <input type="hidden" name="action" ...