点名帖

July 2nd, 2009

被猪头Jessie点到了。

  1. 大名小名?
  2. 大名X小名x全名真多X

  3. 生日?
  4. 1985-06-20

  5. 被谁点名?
  6. JessieLin

  7. 生日最想要什么?
  8. BG大家

  9. 喜欢什么颜色?
  10. 喜欢什么明星?
  11. 我不追星

  12. 喜欢什么歌手,什么歌曲?
  13. 歌手?很少记名字……歌是我觉得好听就喜欢了

  14. 喜欢什么电影?
  15. 很少看电影,无法回答

  16. 喜欢什么电视剧?
  17. 是电视剧我都喜欢泡,但说到喜欢呢……Laughing Gor!

  18. 喜欢什么风格的衣服?
  19. 没有特别要求

  20. 喜欢吃什么?
  21. 辣的和苦的除外

  22. 喜欢什么男人<女人>?
  23. 你如果问不喜欢什么女人我估计还能答,喜欢的话……最紧要将feel的

  24. 近期的心愿?
  25. 完成GAF

  26. 长远目标?
  27. well……一时间答不到。相对长远一点的算不算?做一个“我们的”Galgame。

  28. 近期让你烦恼的事?
  29. 感情的,工作的,是人基本上都会烦恼的那些。

  30. 近期让你失望的事情?
  31. 好像没有?

  32. 近期让你开心的事情?
  33. 今个月的奖金不错

  34. 最近常想起的人?
  35. 老爸+老妈

  36. 觉得自己最得意的事情?
  37. 继续没有?

  38. 自己做过最失望的事情?
  39. 同上

  40. 爱情友情亲情什么重要?
  41. 你没要求单选。不过要不要求我都只会答都重要。

  42. 男女间有纯粹的友谊吗?
  43. 暗恋过别人吗?
  44. 有,而且很多

  45. 主动表白过吗?
  46. 觉得怎样才算浪漫?
  47. 别人都说我木

  48. 做过的事情里有后悔的吗?
  49. 嗯……应该有吧,比如说那个,比如说那那个……

  50. 伤心难过会怎样?
  51. 不定,有时候会流下男儿泪,有时候会打机打发掉,有时候会call朋友打发掉

  52. 最难过是什么时候?
  53. 我发现这些问题好像都差不多……有但不记得了

  54. 无聊怎么打发时间?
  55. 打机,看书,写代码

  56. 会失眠吗?觉得是什么原因引起?
  57. 会,生理性失眠:昨晚通顶了今天一睡睡到下午6点,于是就失眠了。

  58. 理想的生活是怎样的?
  59. 在空调房里面看书,喝咖啡,code

  60. 对点你名人的印象?
  61. 猪头一个

  62. 你们认识多久?
  63. 我还是大三学生时的一个夜晚。她,我人生中一个重要的XX,出现了。
    也就是说有快4年了吧。

  64. 点名者在你心里的位置?
  65. 我生命中认识到的重要的……………
    ………………………………………………
    ………………………………………………
    ………………………………………………
    ……………………猪头中的其中一只。

  66. 记得朋友的生日吗?
  67. 记得,因为有很多东西都会提醒我朋友的生日。

  68. 喜欢哪个城市?
  69. 广州和佛山

  70. 喜欢哪个季节?
  71. 冬天,因为被窝很舒服!

  72. 生活里最三八的人是谁?
  73. 点我名的这个

  74. 为爱的人做过自己觉得了不起的事?
  75. 嗯……好像没?

  76. 口头禅是什么?
  77. 很多的哦!比如说,“嘛”,“囧!”

  78. 重要的日子是什么?
  79. 放假的日子

  80. 最近常笑吗?因为什么?
  81. 我经常笑,没为什么,就爱傻笑

  82. 最近常哭吗?因为什么?
  83. No,因为没什么值得我哭

  84. 如果明天中五百万你第一件事会做什么?
  85. 存起来,然后逐步实施我构想已久的“阳谋”!

  86. 去KTV最拿手的歌?
  87. 我没去过KTV

  88. 异性朋友多不多?同性朋友多不多?
  89. 多不算多,都差不多

  90. 觉得什么才算朋友?
  91. 冇乜具体标准的,我认为是就是了。

  92. 最怕什么?
  93. 蟑螂等一切拍死了以后很核突的生物。

  94. 掉眼泪是软弱的表现吗?
  95. 不一定

  96. 出门第一件事情?
  97. 出门以后的第一件事?关门。

  98. 喜欢的动物是什么?
  99. 狗,猫,马,鸟,很多很多

  100. 有几双鞋子?
  101. 经常只有一双,偶尔两双

  102. 爱逛街吗?
  103. 也说不上喜欢,说不上讨厌

  104. 现在用的包是什么颜色的?
  105. 黑色

  106. 喜欢过白天还是黑夜?
  107. 黑夜,因为最近我很野猫

  108. 对自己哪里最满意?
  109. 没有。

  110. 现在烦不烦?
  111. 之前不是问过了吗?

  112. 如果对恨的人说一句话会说什么?
  113. “……”

  114. 你觉得你和陈冠希哪个帅?
  115. 小时候最深刻的事情?
  116. 被烟花烧到颈了

  117. 觉得自己现在孤单吗?
  118. 不觉得

  119. 如果受伤会怎么抚平?
  120. 过几天就自然抚平了

  121. 有过自杀的想法吗?什么时候?
  122. 有过,不只一次,不过终究只是考虑各种可能性的时候顺带产生的其中一种想法。某一次是在1年半前。

  123. 酒和烟什么比较有吸引力?
  124. 都没有,我都不喜欢

  125. 如果你可以马上实现一个愿望,你希望是?
  126. 变成有钱佬

  127. 觉得多啦A梦和麦兜喜欢哪个?
  128. 麦兜

  129. 现在脑子里想着谁?
  130. 麦兜。因为上一题刚刚答完

  131. 如果遇到坏人怎么办?
  132. 还真的没想过,随机应变吧。

  133. 觉得自己是好人吗?
  134. 算吧

  135. 我的问题多不多?
  136. 很多

  137. 爱谁时间最长?
  138. 算上暗恋的吗?算的话,高中时候从高一暗恋到高三上学期的某女生。

  139. 你记得自己第一个同桌是谁吗?
  140. 太久远了!我的生活和galgame里面的情节差太多,没有所谓的青梅竹马,所以也不会记得。

  141. 为什么你的通讯录里没有我的号码?
  142. 你肯定是吃过期罐头吃多了,居然敢说我的通讯录里面没有你的号码

我可没办法找到10个人那么多去传。鉴于你这个要求太无理,我就不执行了。

X 杂七杂八

[翻译转载][EVE DEV Blog]Apocrypha 1.5,8月见

July 2nd, 2009

原文为EVE DEV Blog 2009年6月30日文:APOCRYPHA 1.5 THIS AUGUEST

自从三月,Apocrypha发布以后,我们就很少从开发最前线上听到新消息了。Apocrypha的发布是EVE Online的一个重大成就。我们把好一些方面都提高到了另一个新高度,例如,在并发游戏人数方面、付费玩家数量方面。更重要的是,我们对Apocrypha中提供的新特性和功能感到自豪。

现在我们正如火如荼地实现冬季更新。说实话,冬季还很远;Apocrypha要搞一个夏季更新还太早了点,于是我们考虑发布一个小型更新,而不是等到冬天才把我们的成果一股脑儿地摆出来。如无意外,八月中就可以看见Apocrypha 1.5的面世了。

小型、中型和大型的船插

你曾经想过弄一艘极速的放风筝专用的护卫舰,但无法承受相关船插的昂贵价格吗?又或者曾经想把你的巡洋舰弄成顶级血牛?抑或是曾经想把你的小小拉货船扩大一点货仓?现在这些想法都能实现了!

我们正准备加入小型和中型尺寸的船插(现有的船插将成为大型船插)。这些船插做起来成本更低,买起来价钱更便宜。我们希望这样做能够让更多的人感受得到船插的乐趣;同时当你的插满船插的船被爆掉的时候,你会少哭一点。CCP Chronitis会在下一篇blog里面作更进一步的说明。

Apocrypha 1.5的Lv4史诗系列

Apocrypha 1.5的内容是非常丰富的。我们加入了一些新的史诗任务系列,与Apocrypha 1中引入的lv 1史诗任务不一样,这些全部是lv 4的,也就意味着这些任务会有富挑战性,理所当然奖励也更丰厚。这些引人入胜的故事会以特定种族为主题,围绕伦理、阴谋、荣誉等等为某些人所欠缺的要素展开。当然这些消息对于那些熟悉EVE以及熟悉我们的工作的人来说这不太算是一个重磅炸弹。和史诗系列在Apocrypha中初次登场的时候一样,这些新的任务给我们展示了一个深入而有趣的故事,而你的选择将会影响故事的结局。

特种货仓 – 黑隐特勤舰的燃料仓

我们正准备引进一个系统,这个系统允许我们在船上部署一个特殊的货仓。我们会从允许在黑隐特勤舰上增加燃料仓开始,陆续还可能会扩展到其他一些船。这意味着我们正为你的燃料增加更多存放的空间;同时也不会破坏平衡性,让黑隐特勤舰变成终极的拉货船。这种技术同时打开了部署其他类型仓库的可能性的门,比如说一个弹药专用舱,生体货物专用舱,等等。这些想法会在未来的资料片里面作进一步探讨。

势力战争新奖赏 – 击杀数LP

我们一直都在密切监视势力战争带来的卡机情况,不断分析网络的行为和玩家的行为,以及详细检查代码。我们收到的那些被报告的卡机现象并不会总是出现,这使得跟踪卡机和解决卡机现象变得困难。目前我们已经分配了工程师去解决这个问题,他们正与我们的质量保证部门和捉虫专家在紧密合作中。

同一时间,为了使势力战争变得更有趣,我们正尝试让击杀和占领都可以获得LP奖励。每个势力都有一个特别的LP商店,提供独占的奖品给势力战争的热衷者们。更详细的内容接下来会有CCP Ytterbium为我们进行介绍。

50%特性 vs 50%维护

我好几次被玩家问到,“花在开发新特性上的时间和花在修补现有的系统的时间大约是怎样分配的”。答案很简单,我们分配了50%的开发时间到新特性的开发上,余下的就分配到对现有系统的修饰、重做以及修补缺陷上。我们认为这样的分配是合理的——不断向前发展的同时维护我们目前已有的。EVE现在已经超过了65万行代码,对比她刚刚发布的时候的28万行,我们认为很多东西都需要得到维护和重构。得益于这些维护的工作,Apocrypha 1.5将会带来为数不少的修补和改进。

冬季更新

跟随着冬季的接近,我们会持续对冬季更新进行报道。目前我可以说的是,冬季更新将关注主权方面的问题,你将无法走进去(声明了主权的星域?)。请持续关注我们dev blog的未来几个月的更新吧。RSS一类东西的狂热者们也可以来订阅我们的RSS

谢谢大家的阅读!

- Torfi Frans

X EVE Online, 游戏 ,

继续流水账

June 18th, 2009

话说最近越来越喜欢尽可能地在Emacs里面搞定一些日常的东西,比如说写的这篇Post。没错,这篇Post是在Emacs里面写的,至于效果如何……其实我也是第一次用……

最近Jessie跟我说打不开我的blog。后来试过实际上打还是能打开的,只不过慢的囧,用了代理可能会有所改善吧。Godaddy的域名是搞得比较有名气的,但主机的部分就马马虎虎。今年过后再找别的空间看看吧。

不过现在才过了半年呢……嘛,访问rss feed是相对比较快点的,所以……欢迎订阅:http://feeds2.feedburner.com/xtheukn

潜水1个多月,都干了些啥呢?嗯……

5月中旬从Raine JJ那里得知网易有道和TC合作搞编程竞赛跑去参加了。其实在大学时期就已经知道Topcoder的大名,只不过一直都没想过去试试。做过好几次练习和比赛以后才倍感自己水平太低了,DIV1的题目只能勉强推倒前两题(有时还推不倒……);然后总喜欢在比赛以后和某人讨论500分的题目,讨论一个多小时后两人一起恍然大悟:“哦!”(或者……“啊啊啊啊啊!”)。几次下来觉得这样的比赛很有趣,虽然到目前为止我还没challenge过别人……嘛,多点参加这样的活动应该对我很有益的,以后也多点参加好了~

上面说的是TC的部分。至于网易有道和TC合作的部分……嘛,算是勉强进入了晋级赛,有件免费的T-Shirt(今天刚刚送到),有个“绿色通道”的机会,接下来就是等着在21日的晋级赛里面当炮灰了。不过当炮灰也当得很有意义就是。

然后其余时间就是玩点游戏和继续开发GAF。嗯……不过开发着开发着,总发现自己的经验还是差很多,想把系统设计得好一点,最终的结果就是已经做好原型改了一次又一次。嘛,这也算是个学习的过程吧,不过效率似乎很低……

最近又燃起了对Galgame的爱了!5、6月里面玩了2个新作,有一个现在仍然在继续,有All Clear的想法啊!逆转口水肩(逆转检事)也在5月底出了,花了不少时间总算通关。老实说我还是喜欢逆转裁判系列多一点,可能是因为逆转口水肩的故事和逆转裁判系列的关联性少吧……不过撇开故事本身,其他方面还是一贯的“逆转”水准,BGM经常听得我热血沸腾啊!


这部分是从Emacs发布以后才加上去的。发布出来的效果似乎不错,只是……permalink没有被pinyin slug转换的样子……另外……=。=我现在还只会发纯文字的。

X 杂七杂八

潜水了一个多月

April 30th, 2009

上浮一下。看看最后一篇写事的post,原来已经是2月份的了,这么说其实我潜水已经有快3个月咯……自己没啥感觉,可能是因为生活一直都不够激情啊。

3月份开始就受raine师姐引诱,一起跳进了GAF的坑里面去了(Well,其实GAF只是我擅自作出来的名字……我们两个并没有在叫什么名字这个问题上花过心思)。然后就发现自己在思维上的诸多不足。嘛,经验不足应该也是一个原因。raine姐你千万别介意多拉我几把啊!

(顺便再BS某sara)

然后现在项目处于”SUCKED”状态。啊神啊,快点给我点灵感吧!

X 生活

[翻译转载][EVE DEV Blog]我们都做了什么

March 12th, 2009

原文为EVE DEV Blog 2009年3月9日文:WHAT HAVE WE DONE!

Hi大家好!这是Epic组的第三篇也是最后一篇《虫洞》发布前的博文了。大家注意别把我们与Epic mission arc组混淆了哦(我们强烈谴责Zulupark,这个名字就是他取的!)。我们负责是设计沉睡者的npc的行为控制机能的。论坛上关于我们的工作的讨论很 多,于是我们发表了这篇博文,旨在解释一下关于沉睡者NPC的问题。

目前EVE里面的NPC控制算法已经做到了这些:

在这次的升级版本*里面,我们又实现了这些:

  • 根据一个可以变动的标准,选择一个最佳目标。
  • 根据一个可以变动的标准,选择第二个目标。NPC将会对这个目标施加效果(可以是对玩家也可以是对NPC的)。
  • NPC之间会互相实施远距离协助。
  • 如果距离目标很远,NPC会使用微跃接近目标。

下面这些我们是没有做改动的的:

  • NPC对玩家的电子战的效果
  • 玩家对NPC的电子战的效果

上面两条包括:缠绕、反跃迁和信号干扰、目标标记,索敌阻扰,信号阻断以及虐能/毁能。2

* 我们说的“升级版本”,是指我们被我们Epic组加强了的NPC控制功能。这个强化我们用在了你将会在虫洞里面遇到的沉睡者NPC上面。

沉睡者与你

这一次实现的这个AI并没有使用任何作弊手段,它只是收集 一些玩家也可以得到的资料,然后利用这些资料决定某一堆NPC的行动。它并不会保留NPC在上一次遭遇战中的数据和战术以提高NPC在这一次遭遇战中的反 应。它会尝试创建一个“可以识别战斗环境的因素,并根据这些因素采取可以最大可能性地取得胜利的行动”(引用来源: http://en.wikipedia.org/wiki/Artificial_intelligence)。这种方法应该不至于让NPC的行动太 过蠢,但离完美还差一大截。

我们把让PvE的经历更接近PvP作为目标。为了达到这个目标,我们设计的控制系统让NPC群体之间的行 为表现得更具合作性。他们会各自选择适合他们的目标,而不是盲目地轰炸某只血牛、完全不理会自己是不是快要被旁边比纸还薄的DPS输出轰至渣了。我们认为 这是可以达到我们预期目标而所需要做出的最重要的修改。当然还有其他方面的改变可以做改动,对所有的电子战效果作修改以让NPC在这方面也能模拟PvP3, 但是我们觉得如果不先提升目标选择的行为,作这样的改动意义不大。而我们也一直坚持了我们的这个修改决定。

几年来,我们一直被玩家要求给予他们更多的挑战,让PvE 中的NPC的行为更像真实的玩家,而不是一堆堆漂在宇宙中等人来捡的赏金。有好一些人对一次又一次单挑一大堆NPC船到底有什么意思。现在,我们给大家带 来了适合你们的PvE战斗,在这些战斗里,你要为生存要斗争。能够在斗争中生存下来得到的不仅仅是丰厚的奖励,还有PvE中久遗的成就感。所有的这些都能 在《虫洞》找到。

关于这种新型NPC的反馈主要都是集中在喜欢solo的玩家,以及这些新NPC对他们带来了什么。实话说当初我们做这个新的NPC行为设计时我们真的没有考 虑到它会引起solo群体的高度关注。我们只是意识到,在每一场的遭遇战中都与同类型的对手交战,很难体现出高超的战术。我们当然可以让沉睡者循规蹈 矩的按照我们给他们的指示在EVE中扮演邪恶的一方,不过我们认为这样做并不会很受我们的顾客欢迎。

于是我们需要平衡遭遇战中 NPC群体的难度的问题。他们的DPS输出能力,他们的挨打能力,或者是电子战技术等等。在“与PvP更接近”的前提下,我们把沉睡者塑造成了与玩家对等 的。所以对于一个技能比较低的玩家来说,一艘装配简单的沉睡者战列舰也会是很吃力的。而一艘强大的沉睡者战列舰,会与某个联盟里面的一个老手飞行员所驾驶 的装备良好战列舰类似。一个驾驶战列巡洋舰的玩家,通过他们喜欢的战术,做出合适的判断的话,应该是有能力灭掉一小群巡洋舰和护卫舰的。不存在一种装配方 案通杀所有遭遇战的,但这正就是游戏的一部分。作为舰船的驾驶员,你必须根据你的能力作出适当的判断。

那么低安全地区的海盗呢?

行星带上面的NPC海盗只做了两方面修改:

  1. 我们在0.1-0.4安全等级的星系里面增加了一些战列舰的刷新,以平衡低安全地区的赏金。
  2. 我们让所有行星带的NPC都是跃进/跃离遭遇地点,而不仅仅是突然出现,然后又突然消失。

看上去似乎挺酷的,让大家的热情突然增加了9000+倍,不过实际上跃进/跃离并没有改变NPC的行为或者刷新机制。事实上这样做的目的,仅仅是让视觉上有一 点变化,让遭遇战变得更真实。有一点很可惜的必须提醒大家,跃迁阻扰是对npc无效的。不过我们想应该会很快搞定的。

另外还有一些Q&A

问:虫洞里面会有solo的内容吗?
答:嗯,有。不过你需要一艘好船,配置要得当。虫洞里面的遭遇战和目前一般的PvE是有很大区别的。我们建议你进入虫洞之前要打起十二分警惕。

问:为什么一些电子战技术对沉睡者无效?
答:正如我们上面解释过的,曾经提议过的一个特性是在PvE改动中,改动电子战的效果以让NPC模拟PvP的行为。然而目前我们认为这是比较次要的,所以这次的releaes里面包含这些。

问:在对沉睡者的战斗里面可以用旗舰吗?
答:只有最大型的虫洞才允许质量巨大的旗舰进入。但我们也想借此机会给那些驾驶旗舰进虫洞的驾驶员一点忠告:别忘了带上一点支援,不然的话……

问:少部分难缠的沉睡者可能会轰掉一艘航母吗?
答:绝对有可能。你可以考虑一下一艘孤军作战的航母面对一队战列舰玩家时候的下场。最坚固的沉睡者基地注定是最有挑战性的,要在对沉睡者的遭遇战中取得成功,就必须要有很好的领导,并且舰队间要分工合作好。

问:为什么沉睡者会锁我的无人机的?
答:试着想象一下在PvP中,如果一个玩家意识到DPS的主要来源是自无人机的话,他会怎样做?作为一个无人机的使用者,请与“我在单打lv4任务”的观点区分一下。你需要用上更多的点子。我们做过很多实际测试,发现这一点已经平衡得不错了。

我们希望这篇博文已经覆盖了大部分你想知道的关于《虫洞》资料片里新NPC的特性。

- Epic组


部分不确定的翻译:

1 Picking a random target as a group or in response to a deadspace complex trigger. 返回

2 The two entries above include: Propulsion, warp and sensor jamming as well as target painting, tracking disrupting, sensor dampening and neut/nos. 返回

3 There were other things up there, such as changing all the E-war effects so that they mimicked PvP. 返回

X EVE Online, 游戏 ,

C++高阶函数(一)

February 23rd, 2009

0. 前言

看见了标题不要以为以下的内容是C++的高级话题。这里的“高阶”是与“函数”连在一起作为名词的。高阶函数(high-order functions)有点借用了数学中高阶的概念。当一个函数是以另一个函数作为参数,或者以另一个函数作为返回值的时候(或者两者兼备),就可以称作是高阶函数。举个例说:

typedef int (*int_func)(int);
 
int f(int_func g, int x) {
   return g(x);
}

这里,函数 f 就可以称作是一个高阶函数,因为它以另一个函数(实参 g )为参数。

高阶函数在函数式编程里面是很普遍,在命令式编程里面可能比较少提到,但对于C++来说,高阶函数已经不是新事物了。很多地方,例如C++的标准库自身,或者C++的巨牛库boost,对在C++中使用高阶函数已经有不同方面的支持。虽然目前还有很多方面我还没有触及到,但为了避免自己没记性忘掉,我还是准备把我不完全的认识先记录下来,日后继续慢慢更新。嗯,期待自己能写出一个系列呢~。

1. 函数的生成

生成函数?

假如现在有一个简单的函数(实际上是函数对象。这里用的是函数的纯抽象概念:只要表现得和函数一样的,都可以叫作“函”。下面的描述,如果不需要严格区分函数和函数对象,那么我一律称作函数),作用是做加法的:

template <class T>
struct x_plus {
   T operator () (T op1, T op2) const {
      return op1+op2;
   }
};

如果有两个int变量x, y,那么

x_plus<int>()(x, y);

得到的结果就是x+y。对于x_plus<int>()来说,它是一个二元函数。

通过把其中一个值变成常量,x_plus<int>()就可以表现像一个一元函数了:

x_plus<int>()(x, 1); //     ---------------     (1)

相当于计算x+1。

函数生成的过程与上面的这个过程是类似的。通过将一个函数的某一个变量绑定为另外一个变量,就可以得到一个新的函数。

然而严格地说,上面的函数调用(1)依旧是二元函数,只不过其中一个参数被固定了。对于一个一元函数,它被期望的调用方式应该是:

_i_am_an_unary_function_(x);

于是,在对于一些需要使用一元函数的场合,x_plus<int>()是无法使用的:

template <class unary_function>
inline int _i_need_an_unary_func (unary_function f, int x) {
   return unary_function(x);
}
 
_i_need_an_unary_func ( x_plus<int>()(x, 1), 10 ); // error

std::bind1st和std::bind2nd

标准库的std::bind1st和std::bind2nd提供了一个解决方案,使得我们可以将x_plus<int>()转化为一个真正的一元函数:

#include<functional>
using namespace std;
 
_i_need_an_unary_func ( bind2nd(x_plus<int>(), 1), 10 ); // ok
_i_need_an_unary_func ( bind2nd(x_plus<int>(), 1), 10 ); // ok

这里的x_plus<>实现于最开始时候定义的有点区别,会在后面说明。

std::bind2nd(x_plus<int>(), 1)和x_plus<int>()(x, 1)的区别在于前者将一个参数绑定到某个已有函数的某个实参上,从而生成一个新的函数,而后者是一个函数调用(而且是不合法的函数调用,这里的 x 会因为未定义而产生编译错误)。所以对于std::bind2nd(x_plus<int>(), 1),以下的调用是合法的:

bind2nd(x_plus<int>(), 1)(10); // ok, equivalent to function call: x_plus<int>()(10, 1)

std::bind1st和std::bind2nd是类似的,区别在于绑定参数的位置不一样:

bind1st(x_plus<int>(), 1)(10); // => x_plus<int>()(1, 10)
bind2nd(x_plus<int>(), 1)(10); // => x_plus<int>()(10, 1)

因为std::bind1st和std::bind2nd的实现是类似的,我只考虑实现其中一个的基本原理:

bind1st返回的可以是普通函数指针或者函数对象,然而对于返回普通函数指针,实现起来似乎不怎么方便>*<,所以一般都是返回函数对象:

template <class F, class A1>
struct x_bind1st_c {
   x_bind1st_c(const F& _f, A1 _a1) : f(_f), a1(_a1) { }
 
   return_type? operator () (argument_type? a2) const {
      return f(a1, a2);
   }
private:
   F f;
   A1 a1;
};

上面的实现还未完整,但不妨先进行分析。通过x_bind1st_c< x_plus<int>, int >(x_plus<int>(), 1),就可以产生一个函数对象func。函数对象里面已经定义了operator()(…)的成员,所以可以通过func(x)的方式来调用这个函数对象,达到预期的效果。

实现中还有部分地方没有明确:operator()(…)的返回类型是什么?实参a2的类型又是什么?或许可以假定为与A1相同,但这毕竟没有普适性:要求一个函数的返回值与实参类型相同、所有实参的类型都一样,这样的要求显然不合理。函数需要返回什么值,实参接受什么类型,是被绑定的函数决定的,如此考虑的话,直接从被绑定函数中获取是最好的方法。为了这样,需要对x_plus<>的定义稍微修改一下:

21
22
23
24
25
26
27
28
29
30
template <class T>
struct x_plus {
   typedef T return_type;
   typedef T arg1_type;
   typedef T arg2_type;
 
   T operator () (T op1, T op2) const {
      return op1+op2;
   }
};

然后……重新写一次完整的x_bind1st_c的定义吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class F>
struct x_bind1st_c {
   typedef typename F::return_type return_type;
   typedef typename F::arg1_type arg1_type;
   typedef typename F::arg2_type arg2_type;
 
   x_bind1st_c(const F& _f, arg1_type _a1) : f(_f), a1(_a1) { }
 
   return_type operator () (arg2_type a2) const {
      return f(a1, a2);
   }
private:
   F f;
   arg1_type a1;
};

x_bind1st_c是一个类模板,使用的时候必须显式指定模板的参数。可以利用函数模板的自动推导简化使用:

16
17
18
19
20
template <class F>
inline x_bind1st_c<F>
x_bind1st(F f, typename F::arg1_type a1) {
   return x_bind1st_c<F>(f, a1);
}

x_bind1st就这样完成了。(我并没有看过标准库的实现,所以我不保证这就是std::bind1st的实现方式。事实上我觉得标准库应该比我上面简单的实现考虑得更多,比如const和volatile关键字的修饰。不过我觉得基本原理应该是这样的。)

x_bind1st(算是简化+删节版的std::bind1st吧,所以下面把两者合在一起统称bind1st/bind2nd)的实现同时也提示了几点:

1、只能用在接受两个参数的函数对象上。

所以对于非二元的函数对象,无法使用bind1st/bind2nd;而且对于普通的函数,因为缺少return_type、arg1_type和arg2_type的定义,所以也不能直接使用;相同的情况存在于类成员函数指针中,不过成员函数指针的情况有点特殊,下面将会提及。

为了让bind1st/bind2nd可以为普通的函数绑定,标准库定义了一个ptr_fun,用来包装普通函数,使得bind1st/bind2nd可以用在普通函数上;对于类成员函数指针,标准库也定义了mem_fun/mem_fun_ref来包装,使得bind1st/bind2nd可以用在成员函数指针上:

int func1(int op1, int op2) {
   return op1+op2;
}
 
struct X {
   int func2(int op) {
      return op;
   }
};
 
std::bind2nd(std::ptr_fuc(func1), 10)(20);
std::bind1st(std::mem_fun(&X::func2), &x)(10);

成员函数X::func2只接受一个参数似乎和之前的说明矛盾。其实这是因为成员函数需要接受一个额外的参数(this指针的由来)。除去这个额外参数以后,就只能再接收一个了。

2、被绑定的参数只能是兼容于被绑定函数的可接收参数的类型(即存在隐式转换)。

简单的说就是你不能这样调用bind1st/bind2nd来实现生成类似于f(x)=(10+x)+x的函数:

std::bind1st(
   x_plus<int>(),
   std::bind1st(x_plus<int>(), 10)
)(20);

原因很简单,因为经过bind1st/bind2nd后得到的是一个函数。除非原来的函数接受的就是函数类型的参数,否则,由于不存在隐式转换,这样的调用将产生错误。


* 或许可以考虑一下返回的是一个函数指针。但如果返回的是一个函数指针,那么这个函数的定义至少应该类似于:

R bind1st(A2 a2) {
   return &func_to_be_bound(a1_bound, a2);
}

返回值、参数a1和a2的类型先不作考虑。

为了记录func_to_be_bound,bind1st必须定义为一个函数模板。这样的话就要求函数的参数列表中须新增用来接受func_to_be_bound的形参。这样的话又会破环bind1st的接口:

template <class f>
R bind1st(A2 a2, f func_to_be_bound);

另一个可能的形式是这样:

template <class F, F f>
R bind1st(A2 a2) {
   retrun f(a1, a2);
}

这种形式中 f 是一个非类型的模板参数。如果 F 是一个指针类型的话, f 就是一个指针,也能算是整型的非模板参数,所以这样的形式是接受的。问题在于调用须以这样的形式进行:

bind1st(a2_arg);

和之前的bind1st的用法差别甚大。或许可以尝试写一个辅助函数来简化:

template <class F>
R bind1st_aux(F f) {
   return &(bind1st<F, f>);
}

然而这种方式实际使用中会产生编译错误,因为模板的实例化参数使用了函数参数。函数参数的值是在运行期才能决定的,而模板则要求在编译期完成实例化。

而且上面那样的函数模板无法接受非整型的函数对象作为模板参数,除非把函数对象定义为全局变量,并将函数对象的地址作为参数传入。局部变量因为储存在栈区,地址取决于栈的使用状况,故只能在运行期判明,不能用作模板参数(我认为理论上静态变量也是可以的,因为都是储存在静态区,地址是可以在编译期决定的。不过在gcc 3.4.5上只有使用全局对象时编译才能通过)。

暂时能想到的用普通函数指针来实现会存在的问题就这些,似乎对于普通函数指针来说限制是比较多的。如果哪位有用普通函数指针的不错的实现的话,请告诉我吧!

另外,这不知道算不算是函数对象比普通函数要灵活的一个例子呢?

>back<

X C++, 程序设计

February 9th, 2009

房间里面静悄悄的,只能听见秒针走过的声音。我,曾经看着自己手表的浮丝不停地工作,看着时间走过,等待着那一刻。现在,那一刻,突然成为了过去时。回想起自己看过的时间,淡淡的哀伤,渐渐从心底涌出。呵呵,其实有点觉得只是自己的幻觉。

不过,事实,就是那样。

其实我觉得,人之所以会愤怒和会悲哀都有这样一个共同的原因,那就是这两种感情作用的对象,对这个人来说都是重要的。

X 杂七杂八

WinMain->main

February 7th, 2009

我想基本上每一个有Windows GUI编程经历的人都知道:对于一般的Win32 Console程序(就是一般的C/C++程序),程序的入口是main;对于一般的 Win32 GUI程序,程序的入口是WinMain。

对于main不一定就是一般C/C++程序的入口,看过不少相关的评论也算是知道的,main仅仅是一个标准规定的符号;对于GUI程序,如果用前面的情况类比,那么WinMain也不一定就是入口。只不过……你想象过用main来换掉WinMain吗?

我是没有想过的,虽然这说的通,main怎么说都是标准的定义,WinMain不过是微软自己定的,但main没有WinMain定义的参数。再说进入WinMain之前的“初始化”也可能和进入main之前的不一样。

不过经过今晚,尽管无法断言初始化的工作是否一样(十有八九不一样),但是用main来代替WinMain,应该是行得通的。WinMain的四个参数中,第二个一般用不上,第三个和main的第二个差不多,第四个是可以显式指定的,剩下的第一个,可以通过GetModuleHandle(NULL)来获得,结果:

int main () {
 
HINSTANCE hInst = GetModuleHandle(NULL);
 
/*
 
...
 
*/
 
}

然后编译,链接,记得链接上GUI程序所必需的核心库。然后运行,得到的结果和用WinMain写的看上去是一样的,除了多了个黑色底的console window。

X 程序设计

又一年开始了

February 1st, 2009

转眼,春节的假期就已经结束了。今天是初七人日,我祝大家生日快乐的同时,也拜个晚年,祝大家新年新气象,牛年牛气冲天!

还没来得及回味春节的点滴,就要马上收拾心情迎接又一年的工作了。人越是年长,时间好像就越不够用的样子。Anyway,自己祝自己在这新的一年里面,有新的突破——

——在各种不同的方面。

X 杂七杂八

emacs 23.0.60.1

January 7th, 2009

自从去年狠了心从vim转到emacs以后,emacs就基本上成了我的默认编辑器了。一直以来我总希望把自己的电脑整理得有条理一点,然而每次到最后都是搞成一锅泡收场,而我每次重装电脑前总会把emacs忘记备份一次……

于是每次重装过以后再次用上Emacs就成了一件很囧的事情。emacs不像vim,release的周期太~~~长了,而且为了使用支持unicode的版本,win32上运行的emacs还必须得从源代码编译。虽然有一个叫ntemacs的项目,不过编译日期貌似是前年的了,部分功能和用惯了的CVS HEAD的功能有不少差别(印象中还有些让我受不了的bug)。

而每次编译需要的功夫还不少(仅对win的系统来说):首先你要安装一个cvs的client取获得CVS HEAD,然后为了正常编译,你必须提供cp、rm等等几个命令——就是要装上gnuwin32的coreutils package;然后,为了增加图片/图标的支持,你还必须要有些额外的图像处理库——又是一轮安装;如果不想手动拷贝帮助文件,那还得把texinfo package也装上(对CVS HEAD的emacs来说,还得找版本旧一点的texinfo package,最新版的使用时总会出现错误);这一堆东西搞好了以后,你才有机会去编译emacs。

一堆废话下来,我想说的其实只是:为了避免日后再重复这样的囧工作,我还是把我编译好的在这里暂存一个为好。我编译出来的emacs的版本号见本post标题。编译中加入了sse2优化和no debug的选项。如果哪位和我一样觉得麻烦而又觉得我编译的版本合要求的话,可以在这里下载emacs 23.0.60.1~

同时也在这里备份一个自己的.emacs(.d),虽然不是怎样高级的东西……不过要用的时候没这个东西可是噩梦啊!

X 杂七杂八