由AF再论template

本文介绍了一种利用洛基(Loki)库进行模板元编程的方法,通过AbstractFactory模式的实现来展示如何自动生成代码,包括抽象基类的设计、子类实现问题及Creator规则的创建。

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

template的伟大魅力在于它的自动生成代码能力,基于template的技术,无论多么高深仰或多么花哨,只要你明白它的自动生成代码的本质,问题会好处理很多。

譬如AbstractFactory在template下的loki做法,它只是为了让编译器帮我们生成代码而已,如果你考虑手写代码,问题会好理解很多。

A抽象基类问题

如果你要使用AbstractFactory模式,那你首先要有一个基类,它定义了生成方法。Loki定义了如此一个接口:

template    <class T>
class    AFUnit
{
public:
    
virtual    T*    DoCreate(Type2Type<T>)    = 0;
    
virtual    ~AFUnit();
}
;

这是一个模板化的东西,明显,在不同的类参与作用下,这会被实例化出一系列类,这是与AF有悖的,毕竟AF我们希望使用统一一个基类,为了支持到这一点,Loki使用了强大的外星动力:GenScatterHierarchy。如此我们得到了一个统一的唯一的接口:

template
<
    
class    TList,
    template    
<class>    class    Unit    = AFUnit
>
class    AbstractFactory    :public GenscatterHierarchy<TList,Unit>
{
public:
    typedef    TList    ProductList;
    template    
<class T>
    T
*    Create()
    
{
        Unit
<T>&    unit    = *this;
        
return    unit.DoCreate(Type2Type<T>());
    }

}
;

尽管这个AbstractFactory是一个多类的组合体,只是它可以作为一个类使用处理,但这不仅仅保证了一个唯一的基类,还给我们提供了额外的优势——细粒度化,你可以对不同的模块传递它的不同颗粒,本模块不必知晓任何一点与自己无关的颗粒以及与该颗粒管理的类、包含关系。

我们回顾AF模式,它要求基类只需要提供统一接口。ok,这个AbstractFactory已经满足这个要求了。使用AF的时候抽象基类问题到此得到完美解决。

B子类实现问题

AF有几个要求,子类要继承基类,并且实现基类的方法,子类也应该是一个唯一的类。

基类已经是一个多颗粒的东西,子类必然是多颗粒的,单又要都继承于AbstractorFactory而且又要保证自己的外观是单颗粒的,只有逐一继承最后包装,GenLinearHierarchy可以帮上这个忙,它可以产出都继承于某一类的类(如果你习惯使用loki的时候使用默认参数,我建议你要多全部参数的声明有个了解),而且它可以对TList操作,不要忘记,AbstractFactory也使用了TList,使用同样的TList可以使你得到完美的继承体系。

满足了继承关系,还要重写基类的虚函数,使用policy是个不错的选择,为继承体系中的每个类都加入一个实现了虚函数的policy,这样每个类都有了虚函数的实现,而每个类又恰恰继承于基类,这简直太完美了,巧合还是人为?难以一言蔽之。

template    <class AbstractFact,
            template 
<class,class,> class Creator = OpNewFactoryUnit
            
class TList = typename AbstractFact::ProductList
            
>
class ConcreteFactory
    :
public    GenLinearHierarchy<typename TL::Reverse<TList>::Result,Creator,AbstractFact>
{
public:
    typedef    typename    AbstractFact::ProductList    ProductList;
    typedef    TList        ConcreteProductList;
}
;

使用TL和Creator创建继承于AbstractFact的线性类表,而ConcreteFactory继承于这个线性表,或者可以说ConcreteFactory是对多颗粒的一个单粒度封装。还是太完美了。

到这里实现Creator规则太简单了。

template    <class ConcreteProduct,class Base>
class    OpNewFactoryUnit    :public    Base
{
    typedef    typename    Base::ProductList    BaseProductList;
protected:
    typedef    typename    BaseProductList::Tail    ProductList;
public:
    typedef    typename    BaseProductList::Head    AbstractProduct;
    ConcreteProduct
*    DoCreate(Type2Type<AbstractProduct>)
    
{
        
return    new    ConcreteProduct;
    }

}
;

Creator没有什么特别的,按照指定规则做事而已。

到这里AF已经被Loki包装成完全自动生成代码的东西了,你只需提供少量的信息,就可以批量获取产品,这才是工厂。

    typedef    AbstractFactory<LOKI_TYPELIST_3(Base,Test1,Test2)>    MyKit;
    
//MyKit*    pKit    = new    MyKit;
    
//Test2*    t2    = pKit->Create<Test2>();

    typedef    ConcreteFactory
<MyKit>    MyConKit;

    MyConKit
*    pKit    = new    MyConKit;
    SmartPtr
<Test2>    t2    = pKit->Create<Test2>();
    t2
->say();
    SmartPtr
<Test1>    t3    = pKit->Create<Test1>();
    t3
->say();

不管如何美化,template还是为了生成代码,这是它的本质,用这个本质考虑template参与情况下的问题会容易理解很多。分析使用AF的时候的逐个细节并归纳,你也可以完成这些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值