C_and_CPP 版 (精华区)

发信人: seaboy (浪小), 信区: C_and_CPP
标  题: 模板特化,缺省参数和其他一些有趣的事情 
发信站: 哈工大紫丁香 (2003年06月21日08:51:57 星期六), 站内信件


模板特化,缺省参数和其他一些有趣的事情 
amature 翻译 

-------------------------------------------------------------------------------
-

我们监视着不远处的大门,生怕从木卫二基地尾随而来的入侵者会跟进来。但看来他们很
满足于让我们呆在里面,或至少等我们自己出来。大门那边依然静悄悄一片。 

不管我们是多么警戒,大笨蛋们仍然占领了我们的许多岗哨。我们杀死了很多大笨蛋-有
时是依靠我们的常规武器,有时是外星文物,最起码其中之一可以喷射出高能闪电使得在
它周围想瞄准的任何东西都是非常危险的-但是大笨蛋们似乎是源源不断地产生的,怎么
也杀不完。 

因此兵变并不是我们唯一担心的东西。 


-------------------------------------------------------------------------------
-

“嘿,伙计,事情进展得怎样了?"听到鲍勃的声音,我有点紧张。然而令我吃惊的是-鲍
勃没有摆出他那一贯的高人一等的姿态。他非常地....恕我直言...平易近人。 

"还不坏吧,鲍勃,"我答了一声,同时也转过身来面对他,我们互相凝视了一会。 

"嗯,伙计,我想知道你是否愿意帮我一个忙。" 

我大吃一惊,哑然无语。这个鲍勃,是部门里最差的程序员,热衷于写晦涩的、难于维护
的代码,偏偏却自命不凡,你在一个街区以外就能感受到他那股傲慢劲。他只有在把一大
沓问题扔给我(同时把他的咖啡放在我的书桌上)时才造访我的蜗居,而现在,就这么一
个人,竟然站在我的小屋里,请求我的帮助! 

“啊哈,当然可以,鲍勃,”我最后回到道,“出了什么问题?” 

鲍勃自己坐到了客椅上。"OK,问题就在这里面。 我已经设法把它浓缩成这段源代码”,
他拿过我的键盘并从我的工作站里打开了一个文件。我仔细地看着它: 

#include <iostream>
template<typename T, std::size_t size = 10>
class c
{
  T m[size];
public:
  void print_size() 
  {
    std::cout << size << std::endl;
  }
};
template<> class c<char>
{
  char m[100];
public:
  void print_size()
  {
    std::cout << 100 << std::endl;
  }
};
int main()
{
  c<char>().print_size();
  c<char, 10>().print_size();
}

“首先,我不明白它怎能通过编译。我的意思是,我认为模板的参数必须是一个类或类型
的名字,而不是一个普通参数。” 

我问道:“你是指参数 size_t ?”鲍勃咕哝了一声,我知道他是同意我刚才的问题。“
是的,当我第一次看到一个无类型参数的时候,我的大脑也停顿了一会。我习惯于看到 
class 或 typename 声明而不是通常的参数。Guru肯定这是允许的,但她让我自己到标准
里去查找。你只能使用整型或枚举型,对象或函数的指针或引用,或者是指向成员的指针 
[1] 。实际上,对于整数类型,参数变成了一个整型常量表达式...” 

“~!@#$%^&*?”鲍勃打断了我。 

“一个编译时常量,”我将他的嚎叫翻译成人话。“总之,由于它是整数-哦,也就是说
由于它是编译时常量,就允许你用 size 来声明对象 T 的数组。相当灵活。” 

“自从我学会了这一点,我经常玩弄这样一个念头:使用一个模板来提供一种更加灵活的 
switch 语句,就像,”我打开了一个新的文件,键入下列文字: 

template<int value1, int value2, int value3>
void f(int currentValue)
{
    switch(currentValue)
    {
    case value1:
        ...
    case value2:
        ...
    case value3:
        ...
    }
}
void g()
{
    f<1, 2, 3>(1); // 执行 value1 情形
    f<2, 3, 1>(1); // 执行 value3 情形
}

“我不能拿出一个使用它的实际程序,所以我把它归入‘相当不错,但尚未实际应用’这
一类。” 

“除了其它一些无用的信息,在集会上还提出了一些东西,毫无疑问,”鲍勃打断了我,扫
了一眼他的手表,“哦,伙计,那相当有趣,但是回到我的问题”。他把身体凑过来,关
掉了我的文本窗口并重新打开他先前的程序。“看看,当我编译并运行它后,第一个模板
打印出了100,正如我所预料的,嗯,因为它实例化了那个c 的特化。我期望第二个模板打
印出10,因为我认为用10和那个缺省参数10相匹配,但它也打印出了100。” 

我研究着代码。鲍勃呷了一口咖啡。 

“那好,”我咳了一下来打破沉寂,“我的第一个反应就是我期望这两个模板都打印出10
。” 

“你知道,那是我告诉那个三八的,-哦,我是说我首先想到的。”啊,这更像我所知道
的那个鲍勃-他会用一个下流的名字来称呼Guru。 

“我设法把缺省参数想为‘懒惰的捷径’,”我继续道,“每当我利用缺省参数来东西的时
候,我不得不记住编译器把它当做我实际上已经写了参数来对待。” 

“我知道,”鲍勃没有耐心地说道。他拿过键盘并且对程序作了轻微的修改: 

int main()
{
  c<char>().print_size();
  // compiler acts as if I written
  // c<char, 10>().print_size();
  c<char, 10>().print_size();
}

“对于基模板,这是一个完全匹配。在那种情况下,对于每个size,程序将打印出10,但
是它却打印出了100,那么是什么出了问题呢?”鲍勃不耐烦地问道,同时扫了一眼他的手
表。 

我尽情享受这一刻。不仅因为鲍勃明白我了解一些他不知的东西,而且实际上他正承认这
一点。 

“那并不是缺省参数使用的唯一地方,”我最后说。鲍勃给了我一个询问性的眼光。“特
化也使用它。”我拿过键盘,小心地将鲍勃的咖啡移到了别的地方。“你将特化写成...”
 

template<> class c<char>

“...像你写的那样运行。” 

template<> class c<char, 10>

“因此,”我继续道,“你不是对c 特化,而是对 c特化,那里,模板参数size 是一个整
型常量表达式,其值为10。换句话说,你的程序就像下面写的那样运行:” 

#include <iostream>
template<typename T, std::size_t size = 10>
class c
{
  T m[size];
public:
  void print_size() 
  {
    std::cout << size << std::endl;
  }
};
 
template<> class c<char, 10>
{
  char m[100];
public:
  void print_size()
  {
    std::cout << 100 << std::endl;
  }
};
int main()
{
  c<char, 10>().print_size();
  c<char, 10>().print_size();
}

“我明白了,”鲍勃一边微笑一边在他的椅子上向后伸展。“在 main(), c 的两个实例在
实例化中都进行了特化。”我不喜欢他脸上的笑容。他站起来,用很大的嗓门继续道,“
伙计,你也要记住应用于模板特化的缺省参数。”我被他的突然改变迷惑了。我发现Guru
正在走来,手里像往常一样拿着一本打开的厚书。 

她在鲍勃的前面停了下来:“你为什么要打断我徒弟的投入?”Guru询问道。 

“嘿,娃娃脸,”鲍勃对着Guru微笑道,“我刚刚在这里是向小伙子解释为什么我们所讨论
的程序的正确输出是100 100。”他瞥了一下手表,“是,快要到2点了-我最好去彼得的
办公室并和他讨论这个。” 

Guru和我目送他消失在去彼得.威廉姆斯的办公室的方向。彼得是我们公司上个月被并购后
的新管理者。 

“他领会到了吗?”Guru咕哝着转向我,“现在事情更糟了。”我的胃一阵抽搐。 

“嗯,这全是为了什么?”我问道。 

Guru疲倦地坐在客椅上。鲍勃走了,她也恢复了“正常模式”:“你曾经问过我,鲍勃为
什么仍然在这里,尽管他是一个...",看得出来,她努力地想找到合适的词语。 

“无能、傲慢、讨厌女人...”我补充道,Guru把这些概括到一个词,我绝不敢把这个词复
述给我妈妈,哪怕她是个聋子。 

“是的,很正确,”Guru继续道,现在她平静下来了,“鲍勃和以前的管理层保持着很密切
的联系。他不知通过什么方法使他们被蒙蔽地认为他是个很好地...极其好的男孩。我想暴
露他的真实本性的所有努力都被扫到了一边,因为他使上面深信我仍然痛苦于我们的离婚
。好像!” 

“总之,”她继续道,“当我们的管理层进行变化的时候,我发现了一个极好的机会。我
说服彼得.威廉姆斯,扔给他一个有挑战性的问题,这问题鲍勃肯定无法解决,我是这么认
为的,而彼得也同意这个问题是极其简单的,即使让你来回答也不会有任何问题。”我被
刺痛了,但是正专注意解释的Guru没顾及我的反应,“如果鲍勃不能在两点前找到答案,
彼得将会密切关注他,或许甚至将他放到实习的位置上。最终,我坚信可以使鲍勃得到他
应得的-一张解雇通知书。可是现在,这将变得更加艰难。” 

她叹息,悄悄地站起来,无声地走开。 

我的胃酸涌过了喉咙里。“我做了什么?”我朝自己嘀咕着。 


-------------------------------------------------------------------------------
-

就在黎明前,反叛者行动了,好几个军官全副武装地走进了达罗萨的帐篷,同时,我们很
快发现只有反叛的军官们有着能使用的武器。达罗萨没有做真正的抵抗,我想他很疲乏而
且已经听天由命,觉得再抵抗也是徒劳,于是乖乖缴械,辛克尔接过指挥权,我们准备投
降。 

一个人被派出去向大门里投了一封投降信。当信被拿起的时候,通过大门我们可以看到一
个短暂的移动,不久传来了答复。依照指示,我们放下了武器,一个接一个地列队通过大
门。轮到我时,我走进了那个昏暗的跳舞场,转身发现自己凝视着表情冷酷的人们手里所拿
着的武器。我叹息,和其他人一样被绑了起来。 


-------------------------------------------------------------------------------
-

[参考文献]
[1] ISO C++ Standard, IOS/IEC 14882, clause 14.1 paragraph 4. 


-------------------------------------------------------------------------------
-

[感谢]
感谢sergei(sergei@summertime.mtu...)在comp.lang.c++上对问题的回答,才能产生这篇
文章。
 
--
才知道   
原来
自己需要的是   
100万
份勇气。。。

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.239.80]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:5.095毫秒