Modern C++ design 第三章 (上)

本文深入探讨了C++中的模板元编程,重点介绍了typelist的定义、操作和实现,包括计算长度、索引访问、查找、追加、删除、去除重复类型、替换和部分排序等功能。通过实例展示了编译时编程的强大之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从哪里来看,这章都是这整本书的重中之重: 介绍了模板元编程, 编译期间编程的利器。 同时实现了typelist这个整本书为之基石的类。 虽说模板元编程晦涩难懂, 但是作者以渐进的方式, typelist为例, 将之阐述的条例清楚, 只要有一定的template基础, 还是能够看明白的了。

typelist的目的:  是为了用同样的代码来泛型处理不同类型, 只需要提供一系列的类型,那么就会自动为这一系列类型生成代码。

typlist的定义: 由一系列类型组合而成的list, 为了实现编译期的递归处理, typelist采用了一种递归定义方法:如:

#define LOKI_TYPELIST_1(T1) ::Loki::Typelist<T1, ::Loki::NullType>

#define LOKI_TYPELIST_2(T1, T2) ::Loki::Typelist<T1, LOKI_TYPELIST_1(T2) >

#define LOKI_TYPELIST_3(T1, T2, T3) ::Loki::Typelist<T1, LOKI_TYPELIST_2(T2, T3) >

更大的typelist由比他小1的typelist加一个类型构成。

接下来, 介绍了各种typelist的操作,  作者由简入深, 通过介绍这些操作, 将模板元编程的奥妙展现无遗。

1. 计算长度.  这是一个递归运算, 第一个特化, 意思是当递归到起点, 没有类型的时候, 此时:TList为NullType. 长度=0.第二个特化就是递归定义, 当长度不等于0的时候, 长度= 1 +  去掉头的typelist的长度。 相当于我们程序实现了一个递归。 区别只是: 这里利用了编译期间的模板实现来进行递归。

        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 };
        };

从这里可以看出编译期实现的一些特性:

1. Template, 模板提供了编译期的分支语句, 即通过不同的类型或者值(值经过intToType包装,相当于不同的类型), 生成不同的特化版本。相当于实现了不同类型之间的差异性。

2.  数值计算: 编译期间只能使用常量, 所以任何辅助的值都是常量。

3. typedefs , 可以用作定义类型常量, 当然,这个类型定义之后就不能改变了。

由于编译期间没有任何的变量可以使用, 所以只能用递归实现行为了。

2. 索引访问 提供了根据索引得到typelist中的对应类型. 递归方式类似length.

        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 i>
        struct TypeAt<Typelist<Head, Tail>, i>
        {
            typedef typename TypeAt<Tail, i - 1>::Result Result;
        };

3. 查找typelists 提供了在typelist中搜索T的行为。 是一个古典的递归线性查找, 可以看出, 模板的特化步骤就是线性查找的实现.

       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) };
        };

4. Append, 加入新的元素, 加入到typelist的尾部, 同样使用递归:

       template <class TList, class T> struct Append;
       
        template <> struct Append<NullType, NullType>
        {
            typedef NullType Result;
        };
       
        template <class T> struct Append<NullType, T>
        {
            typedef Typelist<T,NullType> Result;
        };

        template <class Head, class Tail>
        struct Append<NullType, Typelist<Head, Tail> >
        {
            typedef Typelist<Head, Tail> Result;
        };
       
        template <class Head, class Tail, class T>
        struct Append<Typelist<Head, Tail>, T>
        {
            typedef Typelist<Head,
                    typename Append<Tail, T>::Result>
                Result;
        };

5. Erase 去处typelist中的第一个特定类型    

 template <class TList, class T> struct Erase;
       
        template <class T>                         // Specialization 1
        struct Erase<NullType, T>
        {
            typedef NullType Result;
        };

        template <class T, class Tail>             // Specialization 2
        struct Erase<Typelist<T, Tail>, T>
        {
            typedef Tail Result;
        };

        template <class Head, class Tail, class T> // Specialization 3
        struct Erase<Typelist<Head, Tail>, T>
        {
            typedef Typelist<Head,
                    typename Erase<Tail, T>::Result>
                Result;
        };

6. EraseAll, 去处typelist中的所有特定类型

     template <class TList, class T> struct EraseAll;
        template <class T>
        struct EraseAll<NullType, T>
        {
            typedef NullType Result;
        };
        template <class T, class Tail>
        struct EraseAll<Typelist<T, Tail>, T>
        {
            // Go all the way down the list removing the type
            typedef typename EraseAll<Tail, T>::Result Result;
        };
        template <class Head, class Tail, class T>
        struct EraseAll<Typelist<Head, Tail>, T>
        {
            // Go all the way down the list removing the type
            typedef Typelist<Head,
                    typename EraseAll<Tail, T>::Result>
                Result;
        };

7. 去处重复类型 这个递归使用了Erase, 将typelist分为head, tail. 然后在tail中删去head这个元素类型, 最后将head和删去后的tail连接起来, 完成递归。

     template <class TList> struct NoDuplicates;
       
        template <> struct NoDuplicates<NullType>
        {
            typedef NullType Result;
        };

        template <class Head, class Tail>
        struct NoDuplicates< Typelist<Head, Tail> >
        {
        private:
            typedef typename NoDuplicates<Tail>::Result L1;
            typedef typename Erase<L1, Head>::Result L2;
        public:
            typedef Typelist<Head, L2> Result;
        };

8. Replace 取代某个特定元素

       template <class TList, class T, class U> struct Replace;
       
        template <class T, class U>
        struct Replace<NullType, T, U>
        {
            typedef NullType Result;
        };

        template <class T, class Tail, class U>
        struct Replace<Typelist<T, Tail>, T, U>
        {
            typedef Typelist<U, Tail> Result;
        };

        template <class Head, class Tail, class T, class U>
        struct Replace<Typelist<Head, Tail>, T, U>
        {
            typedef Typelist<Head,
                    typename Replace<Tail, T, U>::Result>
                Result;
        };

9. 部分排序: 以派生关系为依据,对typelist中的类型进行排序。 当然, 这里要用到以前所实现的SUPERSUBCLASS, 用以判断两个类型之间的派生关系。

MostDerived: 以T为基类, 在typelist中找到以T为基类的派生顺序的最底层。

       template <class TList, class T> struct MostDerived;
       
        template <class T>
        struct MostDerived<NullType, T>
        {
            typedef T Result;
        };
       
        template <class Head, class Tail, class T>
        struct MostDerived<Typelist<Head, Tail>, T>
        {
        private:
            typedef typename MostDerived<Tail, T>::Result Candidate;
        public:
            typedef typename Select<
                SuperSubclass<Candidate,Head>::value,
                    Head, Candidate>::Result Result;
        };
DerivedToFront:  实现了最终算法, 这个算法应用了MostDerived:

      template <class TList> struct DerivedToFront;
       
        template <>
        struct DerivedToFront<NullType>
        {
            typedef NullType Result;
        };
       
        template <class Head, class Tail>
        struct DerivedToFront< Typelist<Head, Tail> >
        {
        private:
            typedef typename MostDerived<Tail, Head>::Result
                TheMostDerived;
            typedef typename Replace<Tail,
                TheMostDerived, Head>::Result Temp;
            typedef typename DerivedToFront<Temp>::Result L;
        public:
            typedef Typelist<TheMostDerived, L> Result;
        };

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值