编译期编程的世界(2/3)

对于给typelist附加元素,我写的代码比较简单,但这个话题可不简单。typelist是编译阶段的链表行为类型链表,对于push_front而言,仅仅需要重新定义一个类型就可以了,但是我们这里谈的是push_back,所以其实是在NullType前进行插入元素,这里的首要问题是找到NullType的位置,找到了它就是push_front行为了。移除某个元素的时候,我们遇到同样的问题,你首先要定位,很幸运,我们有编译期的if手段,通过递归推导,我们可以漂亮的完成这个任务:

6.移除typelist中的某个元素

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

在找到T-Tail段的时候,我们移除了T,是的,你也许想到了,在这个时候继续递归推导,我们可以移除typelist里所有元素。

7.移除所有元素

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

一切都那么自然,我们在之前已经考虑到了所有问题Erase和EraseAll只是一个类型的替换,但编译器为你做了很多推导。

8.移除重复元素

移除重复元素其实是对每个Head而言你对Tail调用EraseAll,这个想法很好,你也许想了解一下移除重复元素的递归思维,这也是对的,希望你的想法是先有前者后有后者,这样的思维负担要小很多。

实际中Loki使用了类这样的方法:

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

 

其实单递归而言,你有多种选择,你可以从从头元素开始依次查找,也可以从尾开始查找到头,但是,找到这个问题得简单优雅的解决方式的思维过程是让人憧憬的,多思考这些你会提高很多。

你可以有多种解决问题的方法,但是请不要停止对优雅的追逐。

9.取代typelist中的某个元素

如果是取代Head,这没有任何问题,否则,你要找到T的位置,或者说就是让它变成Head,这太简单了。

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

有了这点代码和我们一直追求的思想,取代所有类型自然不再话下。

10.为typelist局部更换次序

正如虚函数可以保证最深的继承被调用一样,对于typelist而言,你可能希望它有一定的顺序以执行某些任务,譬如双分派。如在移除重复元素时的经验,你需要递归推导,重新定义一个类型存放结果是个不错的选择,这样可以减缓思维的压力。

这里有若干问题,首先如何判断继承关系,很幸运,之前我们讨论的SUPERSUBCLASS可以解决这个问题,其次如何找到最末端的继承者,你可以一个一个的比较,是的,类型选择可以解决这个问题,让我们包装一下类型选择使之可以找到

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),Head,Candidate>::Result    Result;
}
;

如果你对前面的每个细节都很认真,那你一定会觉得这些代码很熟悉,你可以用心去思考设计深处的东西,如果你不是,那你要复习以前的东西,其实这是一个平衡,技术来不得半点虚假和造作。

如此可以用迭代的方式进行排序:

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

事情就是这样的,选择,筛除,构造。

引用Andrei的话,你可能认为typelist很有魅力、很有趣、或者很丑陋,其实你还没有真正看到什么东西。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值