`

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++11 TypeList 妙用

    源码展示: #include using namespace std; template &lt;typename&gt; struct typelist; typedef typelist &lt;int&gt; defaultPolicys; template &lt;typename&gt; struct ... struct concat&lt;typelist&gt;, typelist&lt;B&gt; &gt; { typ

    javabean分页程序

    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分页的例子

    javabean分页程序,适合初学jsp的朋友 &lt;br&gt;1、数据库表中有GoodsType表 2、新建TypeList.jsp页面 3、新建GoodsType的实体类 4、新建GoodsTypeDAO的操作类 5、在BusinessDelegate类中注册相应的方法...

    微信小程序icon组件使用详解

    微信小程序icon组件的实现,具体如下 ... typeList: ['success', 'success_no_circle', 'info', 'warn', 'waiting', 'cancel', 'download', 'search', 'clear'] }, }) 引入图标库 方法 微信小程序—-引入外部字体

    基于传统机器学习DNN算法的恶意网站检测python源码+数据集.zip

    运行typelist.py对特征数据进行可视化展示。 data.zip中的2.xlsx为白名单和黑名单特征的整合。 运行SVM.py、forest_split.py、DNN.py机器学习训练和预测数据(其中DNN用到的是DNN的分类算法)。 基于传统机器学习...

    表达式的求解,可以是多位数和小数

    Type list[MAX_SIZE]; int top;//标记 public: Stack(); void Push(const Type & a);//入栈 Type Pop();//出栈 void Clear();//清空栈 Type GetTop();//获取栈顶元素 bool IsEmpty()const;//判断...

    .Net在线考试系统网站.zip

    要求:1、服务器环境:.Net2.0 + IIs 2、在/js/common.js中typeList参数可以修改题目类型以及抽题方式 3、web.config可以配置每种类型题目的数量 4、题库可以设置题目的分值 5、在/js/exam.js中可以设置考试时间之类...

    type_list:C ++ type_list类型(仅允许将文字类型用作type_list元素)

    type_list 另一个type_list实现(C ++ 17;仅允许将文字类型用作type_list元素;已测试:MSVC 2019 16.9.2,GNU g ++ 10.1.0,clang 10.0)

    flash support list

    flash type list,包含三星,intel.镁光

    基于传统机器学习的恶意网站检测

    运行typelist.py对特征数据进行可视化展示。 data.zip中的2.xlsx为白名单和黑名单特征的整合。 运行SVM.py、forest_split.py、DNN.py机器学习训练和预测数据(其中DNN用到的是DNN的分类算法)。 &lt;项目介绍&gt; 该资源...

    Loki库源码(泛型模式C++库)

     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. ...

    个人博客jsp代码

    &lt;% ArrayList typelist=(ArrayList)session.getAttribute("artTypeList"); %&gt; 博客后台-发表文章 &lt;tr&gt;&lt;td colspan="2"&gt;&lt;/td&gt;&lt;/tr&gt; &lt;td valign="top"&gt;&lt;/td&gt; &lt;input type="hidden" name="action" ...

    invensense sensor type support list

    invensense sensor type support list

    《数据结构 1800题》

    《数据结构 1800题》 第一章 绪论 一、选择题 1. 算法的计算量的大小称为计算的(B )。【北京邮电大学2000 二、3 (20/8分)】 A.效率 B....2. 算法的时间复杂度取决于(C )【中科院计算所 1998 二、1 (2分)...

    编程新手真言......

    11.1 typelist 205 11.2 traits 206 11.2 policy 206 第四部分 一个例子:游戏引擎和实现 206 第12章 设计(需求分析) 207 12.1 第一天:接到一个案子 207 12.2 第二天:需求分析 208 第13章 设计(领域分析与抽象...

    UMI.Console:具有管道支持的控制台实用程序 UMI.CMS

    统一管理控制台 控制台实用程序 UMI.CMS 安装 ...chmod +x umi-cli.phar ... $ umi type list -nm -n显示标题 -m显示模块方法 显示所有数据类型 $ umi type list -AnG -A显示所有数据类型 -n显示标题 -G显示 GUID -g查

    Oracle ORA-22908(NULL表值的参考)异常分析与解决方法

    场景如下:–创建类型(type)create or replace type list_obj is table of number;–创建表结构create table test( name varchar2(30) primary key check(regexp_like(name,’^([a-z]|[0-9]|_)+$’)), id number not...

Global site tag (gtag.js) - Google Analytics