模板与继承之艺术——命名模板参数

一、命名模板参数
许多模板技术拖着一长串的类型参数,不过很多参数都设有合理的缺省值。
template<typename Policy1 = DefaultPolicy1,
typename Policy2 = DefaultPolicy2,
typename Policy3 = DefaultPolicy3,
typename Policy4 = DefaultPolicy4>
class BreadSlicer{};
 
但是如果我们需要指定某个非缺省实参,还必须明确的指定在它之前的所有实参,即使这些实参跟默认参数一致。
BreadSlicer<DefaultPolicy1, DefaultPolicy2, Custom>
 
如果我们能够实现类似BreadSlicer<Policy3 = Custom>显然更有效率。
思路是这样的:
(1)将参数分派给一个叫做Policy3的东西管理,上面的“=”可以换成模板,将Custom作为模板实参传递进去。
这里我们将Policy3换个名字Policy3_is,然后用Policy3_is<Custom>实现赋值。
(2)将默认实参合并在一起,并用新名字进行索引修改。
class DeafultPolicies{
public:
    typedef DefaultPolicy1 P1;//DefaultPolicy1是具体类,P1是为了索引到该类型
    typedef DefaultPolicy2 P2;
    typedef DefaultPolicy3 P3;
    typedef DefaultPolicy4 P4;
};
然后创建类似Policy3_is类进行管理。
template<typename Policy>
class Policy1_is :  virtual public DefaultPolicies{ //为什么要虚继承?待会揭晓
    typedef Policy P1;   //将P1从新赋值
};
template<typename Policy>
class Policy2_is : virtual public DefaultPolicies{
    typedef Policy P2;
};
。。。//剩下的Policy3_is与Policy4_is类似
上面的四个类可以说是 修改器,那这些修改器要怎样安装,安装到哪里呢?要创建一个有四个“插槽”的“插座”。
在这之前首先解决一个问题,默认参数是什么,根据上面的模式,默认参数应该也从DefaultPolicies继承而来的。
 
class DefaultPolicyArgs : virtual public DefaultPolicies{};//默认实参
”插槽“在插入“修改器”之前应该是被默认实参占领所以,要将四个相同类型(默认实参)同时继承到一个类里面就需要使用一点小技巧。
 
template<typename Base, int D> //使用D将相同的类型编程不同类型,但是类的本质不变,还是子类继承基类
class D : public Base{};
template<typename T1, typename T2, typename T3, typename T4>
class PolicySelector : public D<T1, 1>, public D<T2, 2>, public D<T3, 3>, public D<T4, 4>{};
此处需要多重继承所以为了避免产生二义性,前面的“修改器”和默认参数都需要虚继承
最后就是组装默认参数。
template<typename PolicySetter1 =  DefaultPolicyArgs,
typename PolicySetter2 =  DefaultPolicyArgs,
typename PolicySetter3 =  DefaultPolicyArgs,
typename PolicySetter4 =  DefaultPolicyArgs>
class BreadSlicer{
    typedef PolicySelector<PolicySetter1, PolicySetter2, PolicySetter3, PolicySetter4> Policies;
 
//使用Policies::P1索引第一个实参。
};
就可以直接BreadSlicer<Policy3_is<Custom> > bc;
下面是一个完整的例子。
#include <iostream>
#include <list>
using namespace std;
 
class DefaultPolicy1{};
class DefaultPolicy2{};
class DefaultPolicy3{
    public:
        void print()
        {
            cout << "我是默认参数3" << endl;
        }
};
class DefaultPolicy4{};
 
class DefaultPolicies{    //将默认实参合并
    public:
        typedef DefaultPolicy1 P1;
        typedef DefaultPolicy2 P2;
        typedef DefaultPolicy3 P3;
        typedef DefaultPolicy4 P4;
};
 
class DefaultPolicyArgs : virtual public DefaultPolicies{};
 
template <typename Policy>
class Policy1_is : virtual public DefaultPolicies{
    public:
    typedef  Policy P1;
};
 
template<typename Policy>
class Policy2_is : virtual public DefaultPolicies{
    public:
    typedef Policy P2;
};
 
template<typename Policy>
class Policy3_is : virtual public DefaultPolicies{
    public:
    typedef Policy P3;
};
 
template<typename Policy>
class Policy4_is : virtual public DefaultPolicies{
    public:
    typedef Policy P4;
};
 
template<typename Base, int d>
class D : public Base{};
 
template<typename B1, typename B2, typename B3, typename B4>
class Selector : public D<B1, 1>, public D<B2, 2>, public D<B3, 3>, public D<B4, 4>{};
 
template <typename T1 = DefaultPolicyArgs,
        typename T2 = DefaultPolicyArgs,
        typename T3 = DefaultPolicyArgs,
        typename T4 = DefaultPolicyArgs>
class BreadSlicer{
    typedef Selector<T1, T2, T3, T4> Policies;
    public:
    void print(){
        typename Policies::P3 p3;   //使用其中一个参数类型的例子,
                                    //就用的第三个参数来展示吧
        p3.print();
    }
};
 
class Print3{
    public:
    void print()
    {
        cout << "我是客户参数3" << endl;
    }
};
int main()
{
    //BreadSlicer<> b;
    BreadSlicer<Policy3_is<Print3> > b;
    b.print();
    return 0;
 
 
编辑整理:Claruarius,转载请注明出处。

转载于:https://www.cnblogs.com/claruarius/p/4111904.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值