模版默认参数小探

   我们知道,复杂模版一般都有多个参数且大多数参数都有默认值。假设我们的模版类型有9个参数,其中后7个参数都指定了默认值,且大多数情况下我们都不需要手动填写这些默认参数。这个时候如果我们要给第九个参数指定一个非默认值,结果是我们不得不给前面的6个默认参数都填入模版实参,哪怕是默认值。

   最近看到c++ template 中有这样的解决方案,能够实现只需我们填写那个我们需要填写的默认参数而不去关心其他的参数。下面是该方案的伪代码。

  1
  2//参数相关类型
  3
  4
  5class para1
  6{
  7public:
  8    static void f() {}
  9}
;
 10class para2
 11{
 12public:
 13    static void f() {}
 14}
;
 15
 16class para
 17{
 18public:
 19    typedef para1 p1;
 20    typedef para2 p2;
 21}
;
 22
 23class default_para_is : virtual public para
 24{
 25}
;
 26
 27
 28template <typename _para1>
 29class para1_is : virtual public para
 30{
 31public:
 32    typedef _para1 p1;
 33}
;
 34
 35template <typename _para2>
 36class para2_is : virtual public para
 37{
 38public:
 39    typedef _para2 p2;
 40}
;
 41
 42
 43
 44
 45//参数区分装置
 46
 47template <typename _para, int d>
 48class discriminator : public _para {};
 49
 50template 
 51<
 52typename _para1,
 53typename _para2
 54>
 55class para_selector :
 56    public discriminator<_para1, 1>,
 57    public discriminator<_para2, 2>
 58{
 59
 60}
;
 61
 62
 63
 64//参数使用者
 65
 66template 
 67<
 68typename _para1= default_para_is,
 69typename _para2= default_para_is
 70>
 71class user
 72{
 73public:
 74
 75    //这是我们要使用的类型选择器。
 76    typedef para_selector<_para1, _para2> selector;
 77public:
 78    void f()
 79    {
 80        selector::p1::f();
 81        selector::p2::f();
 82    }

 83}
;
 84
 85
 86//填充参数类型
 87
 88
 89class parameter1
 90{
 91public:
 92    static void f()
 93    {
 94        cout << "p1.f()" << endl;
 95    }

 96}
;
 97
 98
 99class parameter2
100{
101public:
102    static void f()
103    {
104        cout << "p2.f()" << endl;
105    }

106}
;
107
108
109//----------------------------------------------------------------------


该方案测试代码:

 

 1    //----------------------------------------------------------------------
 2
 3
 4
 5
 6    //使用默认参数类型
 7
 8    user<> u1;
 9    u1.f();
10
11
12    //指定参数类型:
13    //        1。能够指定任意一个参数的类型。
14    //        2。指定的参数满足交换律。
15
16    user<para2_is<parameter2> > u2;
17    u2.f();
18
19    user<para1_is<parameter1>, para2_is<parameter2> > u3;
20    u3.f();
21
22
23    user<para2_is<parameter2>, para1_is<parameter1> > u4;
24    u4.f();
25
26
27    //----------------------------------------------------------------------



    上述代码中,类型 user 使用了 para1 para2 两个类型,且两个类型都指定了默认模版实参。我们在给模版形参para2 指定非默认值得时候只是简单的调用设置参数函数user<para2_is<parameter2> > 就行了,并没有对 para1 进行实参填充,这正是我们想要的结果!。

    对上述代码的几点说明:

         1。上述代码有几个继承体系,但都是在编译期间进行的匹配,不会引起运行速度慢等问题。
         2。该方案使用了模版的 trait 和 policy 技术。trait 实现了类型封装。policy 提供了隐式接口和编译期多态的支持。

         3。如果模版参数并不是很多的情况下如此操作只会增加复杂度和出错的可能性。个人感觉参数个数比较多的情况下使用带来的好处是非常大的。
 

posted on 2007-01-29 01:27  小峰  阅读(371)  评论(0)    收藏  举报

导航