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毫秒