<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>溪流软件工作室</title>
	<atom:link href="http://www.streamlet.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.streamlet.org</link>
	<description>漫漫长路远，冷冷幽梦清，雪里一片清静……</description>
	<lastBuildDate>Sun, 05 Feb 2012 08:25:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>溪流 WarKey 3.0 正式版已发布</title>
		<link>http://www.streamlet.org/archives/2012/02/05/356/</link>
		<comments>http://www.streamlet.org/archives/2012/02/05/356/#comments</comments>
		<pubDate>Sun, 05 Feb 2012 08:25:15 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[溪流 WarKey]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/?p=356</guid>
		<description><![CDATA[如题，这个版本与 3.0 beta2 差别不大。
所有需要介入魔兽进程的功能还是没有加上，后续版本再说吧。]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2012/02/05/356/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>发个 溪流 WarKey 3.0 beta2</title>
		<link>http://www.streamlet.org/archives/2012/01/07/337/</link>
		<comments>http://www.streamlet.org/archives/2012/01/07/337/#comments</comments>
		<pubDate>Fri, 06 Jan 2012 16:15:03 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[溪流 WarKey]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/?p=337</guid>
		<description><![CDATA[这个版本把界面重新整理了一下，停用了beta1所用的WTL，使用了自己的GUI框架，同时也使用了xlLib。

开发工具上换成了 VS2010，之前为了小巧和MFC而使用VC6，写起来太不爽了，直接导致开发热情降低。

脚本支持上，lua5.1换成了5.2，lua本身的升级变化还是有一点的，比如访问全局表的方式变了，等等。脚本格式定义还是基本上使用了原来beta1里的，有个NameSpace换成了新的URL，直接指向API说明页面。脚本的参数配置名字，beta1里面是0、1、2之类的数字，并且不允许重命名，现在改成了字符串，可以任意修改。

软件核心功能上，相比3.1，把方案分组和组合键去掉了。方案分组看上去太麻烦了，而组合键，则是技术上做不到太好的用户体验。这么说吧，比如，用户想把按下 Ctrl+A  模拟成按下 B，那么，找到 Ctrl+A 的触发点没问题，但是之后要按下 B 的时候，一般 Ctrl 键没那么快放掉的，于是这个 B 就变成 Ctrl+B 了。主要原因就是这个场景，我举的例子还是最简单的情况，再复杂点，就更不好搞了。所以，在找到有效的技术方案前，这个功能先不搞。

大概就这些，终于把 xlLib 全面用上了，感觉好爽。

软件下载地址见导航栏链接

&#160;

&#160;]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2012/01/07/337/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>还是搞个独立博客玩吧</title>
		<link>http://www.streamlet.org/archives/2011/11/26/8/</link>
		<comments>http://www.streamlet.org/archives/2011/11/26/8/#comments</comments>
		<pubDate>Fri, 25 Nov 2011 17:43:10 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[.未分类.]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/?p=8</guid>
		<description><![CDATA[一年前在 bluehost 的 wp 数据库好像是忘了备份回来，所以以前的文章都没有了，有点点可惜了。不过还好数量不大。

原来的首页就不用了，维护太麻烦，直接把 WP 当首页了。

<a href="xlwarkey/">下载溪流 WarKey </a>的同学请从左边或者上面的链接进入。

软件好久没更新了，近期开始重新运作。

[ad#ad-1]]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2011/11/26/8/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>如果要拟定一份代码规范，哪些内容应该列入？</title>
		<link>http://www.streamlet.org/archives/2011/07/13/171/</link>
		<comments>http://www.streamlet.org/archives/2011/07/13/171/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 22:22:00 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/2011/07/13/%e5%a6%82%e6%9e%9c%e8%a6%81%e6%8b%9f%e5%ae%9a%e4%b8%80%e4%bb%bd%e4%bb%a3%e7%a0%81%e8%a7%84%e8%8c%83%ef%bc%8c%e5%93%aa%e4%ba%9b%e5%86%85%e5%ae%b9%e5%ba%94%e8%af%a5%e5%88%97%e5%85%a5%ef%bc%9f/</guid>
		<description><![CDATA[<p>如题，大致看了下网上能找到的一些规范，觉得大体有这么三个方面吧，一个是排版方面的，一个是命名方面的，一个是书写逻辑方面的。</p> <p>排版方面的大概有，如何缩进，如何使用空格、换行，等等。命名方面的包括变量、函数、类、文件的取名等等。书写逻辑方面的就比较多了，可能包括：<br />是否全面使用异常、出错处理资源清理如何组织、如何利用编译提示防止常见错误……</p> <p>一时间列不全。网上常见的文档我会参考的。除此之外，想从大家这里征求下，以上几个大方面之外，还有没有比较重要的方面？大家日常工作中有没有遇到一些特别希望别人也使用和自己一样的方式做的事？以及，哪些规定比较容易被推动？哪些规定不容易被推动？如果有一个规则强加在你头上，你会有怎样的心理？等等……</p> <p>如果您有想法，请回复下，我们讨论讨论^_^</p> <p>----------</p> <p>顺便再问个问题，Windows 上的开发，大家喜欢动态链接 CRT（/MD、/MDd） 还是静态链接 CRT（/MT、/MTd）？为什么？个人倾向于哪种？在公司里又是怎样做的？</p>]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2011/07/13/171/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何写 执行耗时任务的、可随时立即退出的函数 呢？</title>
		<link>http://www.streamlet.org/archives/2011/05/26/172/</link>
		<comments>http://www.streamlet.org/archives/2011/05/26/172/#comments</comments>
		<pubDate>Thu, 26 May 2011 00:36:00 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/2011/05/26/%e5%a6%82%e4%bd%95%e5%86%99-%e6%89%a7%e8%a1%8c%e8%80%97%e6%97%b6%e4%bb%bb%e5%8a%a1%e7%9a%84%e3%80%81%e5%8f%af%e9%9a%8f%e6%97%b6%e7%ab%8b%e5%8d%b3%e9%80%80%e5%87%ba%e7%9a%84%e5%87%bd%e6%95%b0-%e5%91%a2/</guid>
		<description><![CDATA[<p>如题。</p> <p>稍微解释下，因为有可能有人会误会：放新线程里面去不就可以了？这没有解决问题。如此的话，你那个线程函数怎么写？或者线程函数里调用的某个任务函数怎么写？总之，多线程虽然总是出现在这些问题的解决方案中，但不是多线程解决了这个问题。嗯……不知道说清楚了没？</p> <p>目前我心里的答案只有这一种模式：</p> <p>bool DoTask(HANDLE hQuitSignal)<br />{<br />&#160;&#160;&#160; while (!QuitCondition)<br />&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (WaitForSingleObject(hQuitSignal, 0) == WAIT_OBJECT_0)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p> <p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; // Do something<br />&#160;&#160;&#160; }</p> <p>&#160;&#160;&#160; return true;<br />}<br /></p> <p>其中，“// Do something”部分要细化到瞬间执行完成的细度。</p> <p>但是我很困惑的是，如果这些任务很繁重，难道我必须每进行一些操作就 if (WaitForSingleObject(hQuitSignal, 0) == WAIT_OBJECT_0) 检查下吗？这样岂不是这种检测代码充斥在任务中了？</p> <p>不知各位有何经验和体会，求教~</p>]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2011/05/26/172/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>一个简单的 Tuple 实现</title>
		<link>http://www.streamlet.org/archives/2011/04/29/173/</link>
		<comments>http://www.streamlet.org/archives/2011/04/29/173/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 22:05:00 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/2011/04/29/%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84-tuple-%e5%ae%9e%e7%8e%b0/</guid>
		<description><![CDATA[<p>标题中说的 Tuple 是指类似 boost::tuple 这样的设施。</p> <p>很多时候我们需要返回/传入一堆参数，所以不得不每次定义一些为了数据传输的结构。Tuple 就是用来解决这一问题的，它提供即时构造一个这样的结构体的功能。而所付出的代价是，丧失各个成员的明确含义，只留下成员的序号。</p> <p>两个元素的 Tuple 就是 Pair，如 std::pair。下面我们来建立针对有限个元素的 Tuple。对于一个元素、两个元素、三个元素，我们可以分别如下实现：</p> <p><font face="Consolas">template &#60;typename T0&#62;<br />struct Tuple<br />{<br />&#160;&#160;&#160; T0 _0;<br />};</font></p> <p><font face="Consolas">template &#60;typename T0, typename T1&#62;<br />struct Tuple<br />{<br />&#160;&#160;&#160; T0 _1;<br />&#160;&#160;&#160; T1 _1;<br />};</font></p> <p><font face="Consolas">template &#60;typename T0, typename T1, typename T2&#62;<br />struct Tuple<br />{<br />&#160;&#160;&#160; T0 _1;<br />&#160;&#160;&#160; T1 _1;<br />&#160;&#160;&#160; T2 _2;<br />};</font></p> <p>但是这三个写在一起，就会出错。为此，我们可以先定义一个含足够多模版参数的 Tuple，然后上面三个分别作为偏特化版本：</p> <p><font face="Consolas">template &#60;typename T0 = NullType, typename T1= NullType, typename T2= NullType, typename T3= NullType, typename T4= NullType&#62;<br />struct Tuple;</font></p> <p><font face="Consolas">template &#60;typename T0&#62;<br />struct Tuple&#60;T0&#62;<br />{<br />&#160;&#160;&#160; T0 _0;<br />};</font></p> <p><font face="Consolas">template &#60;typename T0, typename T1&#62;<br />struct Tuple&#60;T0, T1&#62;<br />{<br />&#160;&#160;&#160; T0 _1;<br />&#160;&#160;&#160; T1 _1;<br />};</font></p> <p><font face="Consolas">template &#60;typename T0, typename T1, typename T2&#62;<br />struct Tuple&#60;T0, T1, T2&#62;<br />{<br />&#160;&#160;&#160; T0 _1;<br />&#160;&#160;&#160; T1 _1;<br />&#160;&#160;&#160; T2 _2;<br />};</font></p> <p>如果手写的话，这也可以。如果不手写，我们可以继续用之前《<a href="http://www.cppblog.com/Streamlet/archive/2011/01/17/138693.html" target="_blank">C++ 下 Function 对象的实现（下）</a>》中的宏循环方案。此方案的一个正式版本见 <a title="xlMacros.h" href="http://xllib.codeplex.com/SourceControl/changeset/view/7851#124600" target="_blank">xlMacros.h</a>。</p> <p>定义带默认值 NullType 的模版参数声明序列如下：</p> <p><font face="Consolas">#define XL_TUPLE_TYPENAME_DECLARE_NT_PATTERN(n)&#160;&#160;&#160;&#160; typename T##n = NullType<br />#define XL_TUPLE_TYPENAME_DECLARE_NT(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_TYPENAME_DECLARE_NT_PATTERN, n, XL_COMMA)</font><br /></p> <p>它将被展开为： <font face="Consolas">typename T0 = NullType, typename T1 = NullType, typename T2 = NullType, …, typename Tn = NullType</font></p> <p>定义不带默认值的模版参数声明序列如下：</p> <p><font face="Consolas">#define XL_TUPLE_TYPENAME_DECLARE_PATTERN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160; typename T##n<br />#define XL_TUPLE_TYPENAME_DECLARE(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_TYPENAME_DECLARE_PATTERN, n, XL_COMMA)</font><br /></p> <p>它将被展开为：<font face="Consolas">typename T0, typename T1, typename T2, …, typename Tn</font></p> <p>定义模版参数使用序列如下：</p> <p><font face="Consolas">#define XL_TUPLE_TYPENAME_LIST_PATTERN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; T##n<br />#define XL_TUPLE_TYPENAME_LIST(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_TYPENAME_LIST_PATTERN, n, XL_COMMA)<br /></font></p> <p>它将被展开为 <font face="Consolas">T0, T1, T2, …, Tn</font></p> <p>定义成员变量声明序列如下：</p> <p><font face="Consolas">#define XL_TUPLE_MEMBER_DECLARE_PATTERN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; T##n _##n;<br />#define XL_TUPLE_MEMBER_DECLARE(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_MEMBER_DECLARE_PATTERN, n, XL_NIL)<br /></font></p> <p>它将被展开为：<font face="Consolas">T0 _0; T1 _1; T2 _2; … Tn _n;</font></p> <p>现在我们开始组装：</p> <p><font face="Consolas">#ifndef XL_TUPLE_DEFINE_MAX<br />#define XL_TUPLE_DEFINE_MAX&#160; 20<br />#endif<br /></font></p> <p><font face="Consolas">template &#60;XL_TUPLE_TYPENAME_DECLARE_NT(XL_INC(XL_TUPLE_DEFINE_MAX))&#62;<br />struct Tuple;</font></p> <p><font face="Consolas">template &#60;XL_TUPLE_TYPENAME_DECLARE(n)&#62;<br />struct Tuple&#60;XL_TUPLE_TYPENAME_LIST(n)&#62;<br />{<br />&#160;&#160;&#160; XL_TUPLE_MEMBER_DECLARE(n)<br />};</font><br /></p> <p>其中后一个还带有宏参数 n。我们将这整一个定义成宏，然后进行宏循环：</p> <p><font face="Consolas">#define XL_TUPLE_IMPLEMENT_PATTERN(n)&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />template &#60;XL_TUPLE_TYPENAME_DECLARE(n)&#62; \<br />struct Tuple&#60;XL_TUPLE_TYPENAME_LIST(n)&#62; \<br />{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160; XL_TUPLE_MEMBER_DECLARE(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />};&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \</font></p> <p><font face="Consolas">#define XL_TUPLE_IMPLEMENT(n)&#160;&#160;&#160; XL_REPY(XL_TUPLE_IMPLEMENT_PATTERN, n, XL_NIL)<br /></font></p> <p>之后再使用这个宏：</p> <p><font face="Consolas">XL_TUPLE_IMPLEMENT(XL_TUPLE_DEFINE_MAX)</font></p> <p>到此为止，上文一开始提出的 Tuple 已经实现，并支持到最大约 20 个元素左右。</p> <p>然后我们可以考虑增加各种方便使用的功能。</p> <ol> <li>默认构造函数。<br /></li> <li>带有 n 个参数的构造函数。相关宏定义：<br /><font face="Consolas">#define XL_TUPLE_INITIALIZE_LIST_PATTERN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _##n(_##n)<br />#define XL_TUPLE_INITIALIZE_LIST(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_INITIALIZE_LIST_PATTERN, n, XL_COMMA)<br /></font></li> <li>拷贝构造函数。相关宏定义：<br /><font face="Consolas">#define XL_TUPLE_INITIALIZE_LIST_COPY_PATTERN(n)&#160;&#160;&#160; _##n(that._##n)<br />#define XL_TUPLE_INITIALIZE_LIST_COPY(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_INITIALIZE_LIST_COPY_PATTERN, n, XL_COMMA)<br /></font></li> <li><font face="Consolas">赋值函数：<br />#define XL_TUPLE_ASSIGN_PATTERN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; this-&#62;_##n = that._##n;<br />#define XL_TUPLE_ASSIGN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_ASSIGN_PATTERN, n, XL_NIL)<br /></font></li> <li><font face="Consolas">各种比较函数。请注意对各元素的相应比较运算符的依赖。这里定义成，Tuple 的 &#60; 只依赖于各元素的 &#60;，Tuple 的 != 也只依赖于各元素的 !=，如此类推。<br /></font><font face="Consolas"><br />#define XL_TUPLE_EQUAL_PATTERN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; this-&#62;_##n == that._##n<br />#define XL_TUPLE_EQUAL(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_EQUAL_PATTERN, n, &#38;&#38;)</font></li> <p><font face="Consolas">#define XL_TUPLE_NOT_EQUAL_PATTERN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; this-&#62;_##n != that._##n<br />#define XL_TUPLE_NOT_EQUAL(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_NOT_EQUAL_PATTERN, n, &#124;&#124;)</font></p> <p><font face="Consolas">#define XL_TUPLE_LITTER_PATTERN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (this-&#62;_##n &#60; that._##n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return true;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; else if (that._##n &#60; this-&#62;_##n)&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<br />#define XL_TUPLE_LITTER(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_LITTER_PATTERN, n, XL_NIL)</font></p> <p><font face="Consolas">#define XL_TUPLE_GREATER_PATTERN(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (this-&#62;_##n &#62; that._##n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return true;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; else if (that._##n &#62; this-&#62;_##n)&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<br />#define XL_TUPLE_GREATER(n)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; XL_REPZ(XL_TUPLE_GREATER_PATTERN, n, XL_NIL)<br /></font><br /></p></ol> <p>同时 Tuple 中也增加相应的函数，即可。</p> <p>最终代码见 <a title="xlTuple.h" href="http://xllib.codeplex.com/SourceControl/changeset/view/7851#141911" target="_blank">xlTuple.h</a>，这里不贴了。</p> <p>请多多指正。</p>]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2011/04/29/173/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何实现一个支持不同类型的 max/min 函数？</title>
		<link>http://www.streamlet.org/archives/2011/03/30/174/</link>
		<comments>http://www.streamlet.org/archives/2011/03/30/174/#comments</comments>
		<pubDate>Tue, 29 Mar 2011 21:27:00 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/2011/03/30/%e5%a6%82%e4%bd%95%e5%ae%9e%e7%8e%b0%e4%b8%80%e4%b8%aa%e6%94%af%e6%8c%81%e4%b8%8d%e5%90%8c%e7%b1%bb%e5%9e%8b%e7%9a%84-maxmin-%e5%87%bd%e6%95%b0%ef%bc%9f/</guid>
		<description><![CDATA[<p>有个需求，能否做到实现一个类似这样的函数：</p> <p><font face="Consolas">template &#60;typename T1, typename T2&#62;<br />XXX Min(T1 t1, T2 t2)<br />{<br />&#160;&#160;&#160; return (t1 &#60; t2 ? t1 : t2);<br />}</font>  <p>其中 XXX 是我们要推导出的类型。  <p>以下是一个失败的尝试。  <p>我记得 Loki 里有关于如何判断某个类型能否隐式转换为另一个类型的东西，大意如下：  <p><font face="con">template &#60;typename T, typename U&#62;<br />class Conversion<br />{<br />private:<br />&#160;&#160;&#160; typedef char Small;<br />&#160;&#160;&#160; class Big { char XXX[2]; };<br />&#160;&#160;&#160; static Small Test(U);<br />&#160;&#160;&#160; static Big Test(...);<br />&#160;&#160;&#160; static T MakeT();<br />public:<br />&#160;&#160;&#160; enum<br />&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Exists = (sizeof(Test(MakeT())) == sizeof(Small)),<br />&#160;&#160;&#160; };<br />};</font>  <p>如此，Conversion&#60;T, U&#62;::Exists 就能判断 T 到 U 的转换是否存在了。  <p>然后再搞个选择：  <p><font face="Consolas">template &#60;bool Condition, typename TypeIfTrue, typename TypeIfFalse&#62;<br />struct Select<br />{<br />&#160;&#160;&#160; typedef TypeIfFalse Type;<br />}; </font> <p><font face="Consolas">template &#60;typename TypeIfTrue, typename TypeIfFalse&#62;<br />struct Select&#60;true, TypeIfTrue, TypeIfFalse&#62;<br />{<br />&#160;&#160;&#160; typedef TypeIfTrue Type;<br />};</font>  <p>最后，再来个：  <p>struct NullType;  <p>template &#60;typename T, typename U&#62;<br />struct CommonType<br />{<br />&#160;&#160;&#160; typedef typename Select&#60;Conversion&#60;T, U&#62;::exists, <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; U,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; typename Select&#60;Conversion&#60;U, T&#62;::exists,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; T,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; NullType&#62;::Type<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#62;::Type Type;<br />};  <p>那么 CommonType&#60;T1, T2&#62; 就是 T1 和 T2 之间哪个是他们的共有类型了。  <p>测试：  <p>int main()<br />{<br />&#160;&#160;&#160; CommonType&#60;int, double&#62;::Type m = 0;  <p>&#160;&#160;&#160; return 0;<br />}  <p>调试，确认 m 是 double 的。但是反过来写 CommonType&#60;double, int&#62;::Type m = 0;，m 却是 int 的。  <p>这说明这套机制一开始就有问题，Test(U) 和 Test(…) 两个重载函数中，Test(…) 不会在需要 double 转 int 时胜出。这是第一个问题。  <p>第二个问题，当写下如下代码的时候：  <p>template &#60;typename T1, typename T2&#62;<br />CommonType&#60;T1, T2&#62;::Type Min(T1 t1, T2 t2)<br />{<br />&#160;&#160;&#160; return (t1 &#60; t2 ? t1 : t2);<br />}  <p>编译无法通过。<u>原因是返回类型中的 CommonType 中的模板参数 T、U 无法接受此时还不能确定的 T1、T2。</u></p> <p><font color="#ff0000">(更正：不是这个原因，返回类型前加 typename 即可。现在问题还是第一个问题。)</font></p> <p>请教各位，有没有什么方法做到？欢迎指教~</p> <p>C++ 0x 中就能很方便做到了：</p> <p>template &#60;typename T1, typename T2&#62;<br />auto Min(T1 t1, T2 t2) -&#62; decltype(t1 + t2)<br />{<br />&#160;&#160;&#160; return (t1 &#60; t2 ? t1 : t2);<br />}  <p>int main()<br />{<br />&#160;&#160;&#160; int a = 2;<br />&#160;&#160;&#160; double b = 1.0;<br />&#160;&#160;&#160; auto m = Min(a, b);  <p>&#160;&#160;&#160; return 0;<br />}</p>]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2011/03/30/174/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>觉得 Loki::ScopeGuard 似乎不该在它自己里面 try &#8230; catch &#8230;</title>
		<link>http://www.streamlet.org/archives/2011/03/23/175/</link>
		<comments>http://www.streamlet.org/archives/2011/03/23/175/#comments</comments>
		<pubDate>Wed, 23 Mar 2011 09:39:00 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/2011/03/23/%e8%a7%89%e5%be%97-lokiscopeguard-%e4%bc%bc%e4%b9%8e%e4%b8%8d%e8%af%a5%e5%9c%a8%e5%ae%83%e8%87%aa%e5%b7%b1%e9%87%8c%e9%9d%a2-try-catch/</guid>
		<description><![CDATA[<p>ScopeGuard 只是帮我们调用一个函数而已，至于这个函数是否有异常出来，它不该悄悄地把它吞了，而应该还我们本来面目，不知道是不是？可是为什么几乎所有介绍 ScopeGuard 的文章都说这 try … catch … 用得好呢？</p>]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2011/03/23/175/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>论让座与道德绑架</title>
		<link>http://www.streamlet.org/archives/2011/03/06/176/</link>
		<comments>http://www.streamlet.org/archives/2011/03/06/176/#comments</comments>
		<pubDate>Sat, 05 Mar 2011 16:12:00 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[.未分类.]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/2011/03/06/%e8%ae%ba%e8%ae%a9%e5%ba%a7%e4%b8%8e%e9%81%93%e5%be%b7%e7%bb%91%e6%9e%b6/</guid>
		<description><![CDATA[<p>来句定场语吧：</p> <p>“我也许不同意你让座或者不让座的做法，但我誓死捍卫你选择让与不让的权利。”——伏尔泰&#160; （^_^）</p> <p>&#160;</p> <p>关于这个话题我早在大二的时候就想说了，奈何周围都是自认为道德高尚的大学生朋友，几乎无法沟通——尽管我现在也不期待看到这篇文章的人会认同我的观点。但是我想，社会总比学校现实一点吧。如果看了这篇文章后你觉得不同意，骂过之后，请两年之后再来看看，那时候也许有不一样的理解。^_^</p> <p>可能有人说，让座是件很自然的事情，觉得人家不方便，就让一下，何必上纲上线呢。是的，我也不想上纲上线。但这位同学说的话只强调了一方面，没有抢点另一方面。完整的说，让座或者不让座都是很自然的事，你觉得人家不方便并且自己也愿意，就让一下，如果不想让，也就不用让，没必要上纲上线的。但是悲哀的是，如此自然的事，被一群道德卫士给上纲上线了。</p> <p>不知道大家有没有碰到这样子的例子，自己本来也没注意周围有没有需要让座的，却被某个站着的人“提醒”一下，某某某不方便，你给TA让个座吧。然后不管你让了，或者是没有让了，那个人可能会指责你没有主动站起来，或者指责你没有到最后也没有站起来。</p> <p>这种人我称之为道德卫士。近几年不乏这样的报道，什么某某人拿一百块钱抽某人脸啦，某某老头一屁股坐到某某超短裙女生腿上啦……被让座的事例不断上演。遗憾的是，舆论的声音，几乎被道德卫士劫持，每个人心中都有一个自己的道德的卫士，就像每个小白和小黑的电脑上都有个360卫士一样，告诉我们自己应该支持哪一方，否则就会有道德风险。</p> <p>道德卫士的出现，让这个本不该上纲上线的东西，变成必须要去面对的了。有些迫于道德压力的人，坐公交车的时候就时时刻刻警惕周围是否有老人上来了，是否有人刷了“老人卡”了。像我这样洒脱，一路睡觉或者闭目养神的也有，不过不多。</p> <p>天涯上有篇帖子，LZ论证了“让座是不道德的行为”（<a title="http://www.tianya.cn/publicforum/content/free/1/1967922.shtml" href="http://www.tianya.cn/publicforum/content/free/1/1967922.shtml" target="_blank">http://www.tianya.cn/publicforum/content/free/1/1967922.shtml</a>）。对于这个论点，我不太同意，我认为让座还是道德的行为，是高尚品德的体现。但是看看这样的文章有助于我们解放思想，只有解放思想了，我们才能进一步讨论。全文摘录如下：</p> <p><font color="#9bbb59">今天跟读大一的表弟一起坐公交，中途上来一个老太太，他马上站起来让座，<br />接着就得意地谴责我没有让座，</font></p> <p><font color="#9bbb59">我问：为什么要让座？<br />他说：不让座是不道德的。<br />我问：什么是道德，谁说过让座就是一种道德的行为？<br />他说：你虽然读完了研究生，但是你道德大大的坏。<br />我说：你根本就不知道什么叫道德，让座其实根本就不值得提倡。<br />因为让座根本就是一种不道德的行为。论证如下：</font></p> <p><font color="#9bbb59">一、什么是道德。</font></p> <p><font color="#9bbb59">道德是一种人与人之间的行为规范和资源分配方式。<br />跟道德相应的概念有：礼仪、法制、权力。<br />我们说，孔融让梨是一种有道德的行为。<br />这种行为体现的行为规范是爱护亲人，<br />体现的资源分配方式是先满足亲人的需要。<br />亲人之间有亲缘关系，互相最为亲近，联系最为密切，<br />当遇到困难或者不测之时，亲人最能提供必要的援助<br />因此，爱护亲人，可以保障自己有良好的社会动员能力<br />并可以廉价地动员这种社会资源满足自己的需要。<br />比如儿子孝顺父亲，父亲辛勤劳作供儿子读大学，<br />儿子考上大学有一份好工作回报父亲，<br />这就是道德提倡的。是有道德的表现。</font></p> <p><font color="#9bbb59">二、何为有道德，何为无道德</font></p> <p><font color="#9bbb59">有道德的行为规范，符合人性；儿子孝顺父母，这符合人性的需求。<br />有道德的资源分配方式，能使资源达到最优分配。<br />我们说，爱国家、爱民族是有道德的，因为国家民族是个人生存之本，<br />如果背叛祖国和人民，必将遭到万众唾骂，<br />不但是因为不符合人性，还因为，这是一种十分不合理的资源分配。<br />国家耗费军队、土地、制度、安定等各种资源为每个子民享用<br />但是这个子民却背弃而去，使国家的资源消耗没得到应有回报<br />甚至成为自己的敌人。因此，这是对资源的严重浪费和破坏，是不道德的。</font></p> <p><font color="#9bbb59">三、道德与法律、礼仪、经济之关系</font></p> <p><font color="#9bbb59">礼仪是道德的表现形式之一，法律是最低限度的道德，道德的实施，<br />应当符合经济学原理。<br />违法的行为，必定是法律制定之时违反道德的行为。<br />违反经济规律的行为，必定是一种不好的道德，是有待改良的道德<br />女子死了丈夫不得再嫁，这在古代是一种有道德的行为<br />但是现在却不是什么有道德的行为，因为不符合人性<br />也不符合经济学规律。女子再嫁，可以使下一代得到更好的抚养和教育<br />可以重新建立一个以家庭为基础的基本经济单位，这显然优于守寡<br />只要是违法的行为，则必定是违反道德的行为<br />有人认为，很多法律规定得不合理，违法不一定违反道德<br />这种看法是错误的。法律既然被如此制定，那么就表明统治阶级认可的最低限度的道德如此<br />嫖娼是一种违法行为，因此，嫖娼行为是不道德的<br />有人认为嫖娼符合人性，符合经济学规律，不违反社会道德，但是它是违法的，因此，它是不道德的。所有违法行为，都是不道德的行为。</font></p> <p><font color="#9bbb59">四、让座是一种不道德的行为</font></p> <p><font color="#9bbb59">1、让座不符合人性。除了身体有某种缺陷比如长痔疮之类的人之外，一般人都是希望在公交车上有座位的，可见坐座位符合人性。基本的人性，一般认为六种，包括安全、吃、住、性、舒适、社交。公交上站着容易被盗，而且汽车有紧急情况时，危险度更高，因此，坐着比之站着，更符合人对于安全的需求。而让座，则是将基本需求无偿让渡给一个陌生人，正相当于丛飞自己孩子不闻不问却到处去助学。</font></p> <p><font color="#9bbb59">2、让座不符合经济学规律。张五常认为让座符合经济学规律，他说，公交车上的座位是一种资源，自己此时将座位让给老弱妇幼，是为了在未来，自己老弱病残之时，别人也会将座位让给自己，因此这是一种长远的投资行为。这种说法近乎搞笑。几乎等于说，你把钱扔在地上，别人就捡到钱了，因此，有朝一日别人也会把钱扔在地上，你就也可以捡钱了。这是可笑的，也是说不通的。你让座这种投资行为，不可能产生什么预期的利益，它根本就是无利可图的。</font></p> <p><font color="#9bbb59">自己无利可图不一定就不道德，你把垃圾扔在垃圾箱里你无利可图。你不能认为这不道德，因为从大面积的社会效果来考察，你仍是有利可图的。你把垃圾仍在垃圾桶而不是路上，对于整个社会来说，你降低了公共服务成本，使公共服务将有机会更多从其他方面回报与你。因此，垃圾扔垃圾箱，符合经济规律，也是有道德的行为。</font></p> <p><font color="#9bbb59">但是让座，对于整个社会的资源分配来说，都是一种浪费。因为让座不符合公平原则，先到着不能先占。也不符合效率原则，最有效率的资源分配方式显然是先到者先得，如果先上车的不能坐座位，后上车的却可以凭借强权或者武力夺权先前的座位，那这就是没有效率的分配，而且也不公正。</font></p> <p><font color="#9bbb59">综上所述，让座是一种不道德的行为。</font></p> <p>文中的弟弟何尝不是被从小培养起来的花儿一样的我们呢？不错，我们都曾有过这样的时期，持过这样的观点。但是你是否愿意跳出那个被精心设计的道德枷锁，回到现实生活中来呢？这里声明下，我绝对不是阴谋论者，我只是个实证主义者，和个人主义者。</p> <p>文中的“让座不符合人性”和“让座不符合经济学规律”我非常认同。对此我有以下补充：</p> <p>1、有人可能认为将座位无偿让给一个陌生人是没什么大不了的。“看他们摇摇晃晃挺不容易的”，“小伙子年轻力壮么，站一下就站一下”，等等。请问，他们摇摇晃晃不同意，我们就容易了么？小伙子就都年轻力壮么？小伙子站一下就那么轻松吗？无疑，说这样的话的人，可能自认为站一下是无所谓的，座位不是他的“基本需求”，无关核心利益，所以无偿让渡给一个陌生人是没什么大不了的。当然，你可以这样认为。但是，你绝对没有权利要求别人也这样认为，不是所有人都对座位无所谓的。即便是所有人都“应该”对座位无所谓，为什么老人们就不应该对座位无所谓了呢？更何况，你能想象某些像我一样的傻逼，可能等了两班车，看没座位不上，往前走了两三站走到始发站去搞个位置，座位就是我此刻苦苦追求的核心利益，你还认为放弃这样辛苦得来的座位是无所谓的吗？</p> <p>2、为了自己以后老了有人给自己让座，说得好像很有道理，很换位思考。这也是现在很多人的论据。正如文中说的，这种做法和不随地丢垃圾是两回事，根本不具有可比性，也没法预期。何况，亲爱的你，当你老的站不住走不了的时候，你觉得你那时还会要挤公交车吗？</p> <p>当然，你绝对有权利去挤公交车，不论什么时候。只是，你得知道后果：幸运的话你可能碰上个位置，或者碰上有人给你让座，不幸的话，你也许只能站着。你需要问下自己有没有能力享受公交服务。如果能，那么，去吧；如果不能，你还是要去（当然你有权利去），说明什么？说明你是傻逼。无论你是不是傻逼，你都不能将“别人会给你让座”当作一个理应发生的事情，当作一个前提。所谓“得之，我幸；不得，我命”。有如此坦然心态，那么，你去吧。如果你是幸运的，请虔诚的感谢上苍或者感谢给你制造这个幸运的人。如果你是不幸的，那就默默承受吧。</p> <p>先到先得，是公交车上很自然的规律，在此规律作用下，那些不适合坐公交车的人就会被淘汰，进而选择更适合他们的交通工具。我赞成、尊重、敬佩那种发自内心的资源的让座行为。但是，当让座被道德卫士绑架后，是什么样的局面呢？那就是有人可以违反最基本的规则了，有人可以指指点点，你不能坐，他不能坐，只有某些人可以坐。这跟我们镇上的某些场合是多么相似！每当某个领域的基本制度被人为破坏以后，这个领域便会出现特权阶级，久而久之，便会形成一种惯性，这个领域的所有人都被绑架了，麻木了，以至于认为是理所应当的。这样，事情会发展到怎样的程度，是无法想象的。</p> <p>回到最简单的层面，让我们遵守最基本的规则，先到先得。偶尔有不适合坐公交车的人跑到公交车了，或许会有人给TA让座，TA回去后可能会反思，我坐公交车自己本来就不方便，还害得别人要给我让座，多不好意思啊，下次没事尽量少坐坐；或者没人给TA让座，让TA尝到了代价，下次也会三思而后行。抑或，这次尝到让座的甜头的不适合坐公交车的人，下次可能还是回去坐公交车，但可能没那么幸运了。如此，在自然规律的作用下，不适合坐公交车的人将始终维持在一个较低的水平，将会和公交车能够提供的座位以及让座数量达到动态平衡，一切很和谐，道德卫士也就失去了赖以生存的土壤了。</p> <p>说到这里，我不禁要问问，是谁在怂恿那些不适合坐公交车的人去坐公交车？别的城市不说吧，就说杭州。70岁以上的老人都可以有老人卡，可以免费坐车。这里且不追究为什么一些看上去不太老的人都有老人卡，姑且认为他们都是70岁以上的。我不知道这是在鼓励什么。老人们既然享受了政策优惠，难道还要打破基本公交规律，来享受“制度优惠”吗？</p> <p>还有一个帖子，说得比较激烈，他在解释什么是道德。</p> <p><font color="#9bbb59">面对公德沦丧的现实，你谈个狗屁的道德，有么？在哪呢？</font></p> <p><font color="#9bbb59">什么是道德你弄懂没有？听胡爷给你普及一下这个小学知识：</font></p> <p><font color="#9bbb59">道德，由公德和私德构成。公德占道德九成以上的比例。什么是公德呢？它不是仅指你在公共汽车上给别人让座。公德，主要指的是政府及其工作人员的行为操守，这东西，是用来建立政府公信力的。这部份内容，又占公德的九层以上。</font></p> <p><font color="#9bbb59">现在我问你：政府及官员的公德在哪里？——这部分沦丧，造成了公德整体的沦丧，也就是说，你一辈子不随地吐痰并给孕妇让了一百万次座位所积累起来的善，都不足以抵消任何一次、仅仅一次“依法”暴力拆迁的罪恶；甚至都不足以抵消任何一次随时发生的城管“依法没收”下层民众一筐感鸭蛋的罪恶。</font></p> <p><font color="#9bbb59">公德的沦丧，直接造成了整个道德的沦丧。——不是么？MD，这边你抢老子的咸鸭蛋，那边却要求老子助人为乐？老子没有半夜出去抢劫就算厚道了，你大爷的。</font></p> <p><font color="#9bbb59">别总装火星来客，好像你多天使似的。呸。</font></p> <p>（<a title="http://www.tianya.cn/publicforum/content/no01/1/415843.shtml" href="http://www.tianya.cn/publicforum/content/no01/1/415843.shtml" target="_blank">http://www.tianya.cn/publicforum/content/no01/1/415843.shtml</a>）</p> <p>我且不论他的解释对还是错，只是想说，我们是多么渺小。穷则独善其身吧。如果你要兼济天下，作道德卫士，那么请不要伤害别人。</p> <p>说说我自己吧，我偶尔也会让个座，那是为了什么呢？不错，为了道德优越感，为了由此带来的身心愉悦。当有道德卫士在旁边提醒或者指责我的时候，我发现让我让座的唯一收获都被他们劫持了，我又有什么理由去让座呢？</p> <p>很简单的道理：我可以选择做高尚的人，我也可以选择做不高尚（但至少无害）的人，但是没有人可以逼我做高尚的人。有人甚至打出了“为了尊重生命，拒绝让座”的标语。我认为这才是我们这个时代所需要的，所要反思的，而不是相反的内容。只有这样，我们的道德体系才能得以纠正，不至于在错误的道路上渐行渐远。</p> <p>我又要引用了（<a title="http://hs.hongdou.gxnews.com.cn/viewthread-5062512.html" href="http://hs.hongdou.gxnews.com.cn/viewthread-5062512.html" target="_blank">http://hs.hongdou.gxnews.com.cn/viewthread-5062512.html</a>）：</p> <p><font color="#9bbb59">“我希望有一天，我们能堂堂正正地上公交车，把乘坐公交车当做一段放松的时间，可以欣赏街景，可以打个盹，可以听音乐……不必时时警惕是否周围有需要主动让座的人，遇到有人请求让座也不必像上课做小动作被老师点名般惶恐不安，想让就让，不想让就不让。而且没必要说明原因，为了个座位就要公布难言之隐，难道非要和《唐伯虎点秋香》般比一比谁比谁惨？</font></p> <p><font color="#9bbb59">让座不是必须的，不是义务，必须自愿，只有这样，受助者才会懂得感谢，让座者才不会觉得自己是被迫的，公交车上的互帮互助才会蔚然成风！”</font><br /></p> <p><font color="#9bbb59"></font>&#160;</p> <p><font color="#9bbb59">“好多孕妇和老人，明明快生产了，还是老人太老了，身体不好，少几条钱，得空坐的士了。</font></p> <p><font color="#9bbb59">公交车经常急刹的，好危险的，万一碰伤了，谁人付得起责任？</font></p> <p><font color="#9bbb59">我的朋友一般我都建议，除非实在是经济不好，或者条件限制，一般要求大肚婆和老人家或者病人坐部的士去，反正你要不经常坐的，特事特办。明白吗？</font></p> <p><font color="#9bbb59">这就是文明和道德。比如桂林那些地方，几百人上一部车，站都站不了，等下还要让老人和其他病人小孩，我不得罪的说，司机吃毛的，明明超载，还放那些人上来，有时候，我就不坐，等几班或者出多点钱坐的士。摩的。”</font></p> <p>我也希望有一天，我老了，老到走也走不动，我跑去乘一下公交车，没有老人卡，真碰上有人让座，我抚须而笑：“你的好意爷心领了。爷只是来重温挤公交车的感觉的。”</p> <p>==========</p> <p>最后加篇引用，这个LZ道理说得比我明白：<a title="http://forum.enorth.com.cn/postsShowAction.do?threadId=2931744&#38;page=1" href="http://forum.enorth.com.cn/postsShowAction.do?threadId=2931744&#38;page=1" target="_blank">http://forum.enorth.com.cn/postsShowAction.do?threadId=2931744&#38;page=1</a></p>]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2011/03/06/176/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>一个好玩的玩意儿：VS 的 autoexp.txt</title>
		<link>http://www.streamlet.org/archives/2011/02/28/177/</link>
		<comments>http://www.streamlet.org/archives/2011/02/28/177/#comments</comments>
		<pubDate>Sun, 27 Feb 2011 17:10:00 +0000</pubDate>
		<dc:creator>溪流</dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.streamlet.org/2011/02/28/%e4%b8%80%e4%b8%aa%e5%a5%bd%e7%8e%a9%e7%9a%84%e7%8e%a9%e6%84%8f%e5%84%bf%ef%bc%9avs-%e7%9a%84-autoexp-txt/</guid>
		<description><![CDATA[<p>嗯，写篇文章的目的是为了把我最新（现在是次新）的那篇文章给刷下去——我不想每次看见它了。</p> <p>不知大家有没有发现，当使用 VS 来调试代码的时候，那些 STL 容器的信息会以比较看得懂的方式显示出来：</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_thumb.png" width="862" height="514"></a></p> <p>&#160;</p> <p>而我们自己写的，它只能按照数据成员来显示，如果数据结构稍微复杂点，看这些直接显示的内容得到的有用信息就会很少了：</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_4.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_thumb_1.png" width="746" height="293"></a></p> <p>&#160;</p> <p>那么，是否有办法能让 IDE 按照我们设想的方式来显示数据呢？答案是肯定的。这个配置就位于 autoexp.txt 中（具体路径为 X:\Program Files\Microsoft Visual Studio 10.0\Common7\Packages\Debugger\autoexp.dat，如果是 VS 不同版本，“Microsoft Visual Studio 10.0”中的版本号换成其他的即可，VS 2005 以上版本都支持）。</p> <p>在里面搜索 vector，可以找到作用于 vector 的调试信息显示方式的语句：</p> <table style="color: #4b4b4b" border="0" cellspacing="0" cellpadding="2" width="499"> <tbody> <tr> <td valign="top" width="497"> <p>std::vector&#60;*&#62;{<br />&#160;&#160;&#160; preview (<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; #(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; "[",<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $e._Mylast - $e._Myfirst,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; "](",<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #array(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; expr: $e._Myfirst[$i],<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; size: $e._Mylast - $e._Myfirst<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ),<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ")"<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )<br />&#160;&#160;&#160; )</p> <p>&#160;&#160;&#160; children (<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; #(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #([size] : $e._Mylast - $e._Myfirst),<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #([capacity] : $e._Myend - $e._Myfirst),<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #array(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; expr: $e._Myfirst[$i],<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; size: $e._Mylast - $e._Myfirst<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )<br />&#160;&#160;&#160; )<br />}</p></td></tr></tbody></table> <p>这个语法的详细官方说明好像没有，不过大体上可以猜出来。</p> <p>第一行 std::vector&#60;*&#62; 是类型，说明下面的内容针对 std::vector，并且适用于任意模版参数。紧接着是一个大括号括起来的段落。</p> <p>preview 开始的那一段表示当该变量单行显示的时候该如何显示，也就是下图第二列的样子：<br /><a href="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_thumb_3.png" width="460" height="35"></a></p> <p>IDE 会依次显示 preview(#( … )) 括号内的以逗号分隔的内容，加引号的会原样显示，变量用 $e 引用（将 $e 视为该类型的一个变量）。</p> <p>除了直接引号，变量的运算结果外，这里还可以写一些高级点的玩意儿，如 #array，#list，#tree。</p> <p>#array 的格式为：<br />#array(<br />&#160;&#160;&#160; expr: … ,<br />&#160;&#160;&#160; size:&#160; …<br />)<br />其中 expr 里可以使用 $i，$i 为元素 index，size 表示元素个数。最终的结果为：<br />$i=0时的expr, $i=1时的expr, …, $i=size时的expr。</p> <p>假设有一个结构：<br />struct Vector<br />{<br />&#160;&#160;&#160; int *pData;<br />&#160;&#160;&#160; int nCount;<br />};<br />其中 p 是指向一块 count 个 int 的内存。如果要依次显示这 count 个数字，preview 中应该写：<br />preview (<br />&#160;&#160;&#160; #(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; #array(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; expr: $e.pData[$i],<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; size: $e.nCount<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; )<br />&#160;&#160;&#160; )<br />)</p> <p>#list 的格式为：<br />#list(<br />&#160;&#160;&#160; head: … ,<br />&#160;&#160;&#160; size: … ,<br />&#160;&#160;&#160; next: …<br />) : …<br />其中 head 是指向第一个 Node 的指针，size 表示元素个数，next 表示 Node 中指向下一个 Node 的分量名，最后冒号后面还要写一个 Node 中的值分量，也就是要显示的那个变量。</p> <p>假设有结构：<br />struct ListNode<br />{<br />&#160;&#160;&#160; int nData;<br />&#160;&#160;&#160; ListNode *pNext;<br />};<br />struct List<br />{<br />&#160;&#160;&#160; ListNode *pHead；<br />&#160;&#160;&#160; int nCount;<br />};<br />preview 的写法为：<br />preview (<br />&#160;&#160;&#160; #(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; #list(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; head: $e.pHead,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; size: $e.nCount,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; next: pNext<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) : $e.nData&#160;&#160;&#160; // 注意，这里的 $e 代表 ListNode，上面两个 $e 都代表 List<br />&#160;&#160;&#160; )<br />)</p> <p>#tree的格式为<br />#tree(<br />&#160;&#160;&#160; head: …,<br />&#160;&#160;&#160; left: …,<br />&#160;&#160;&#160; right: …,<br />&#160;&#160;&#160; size: …<br />) : …<br />其中 head 是指向根节点的指针，left 和 right 分别是指向左右子树的分量名，size 表示元素个数，最后冒号后面写节点中的值分量。IDE会对整棵树做中序遍历。</p> <p>假设有结构：<br />struct TreeNode<br />{<br />&#160;&#160;&#160; int nData;<br />&#160;&#160;&#160; TreeNode *pLeft;<br />&#160;&#160;&#160; TreeNode *pRight;<br />};<br />struct Tree<br />{<br />&#160;&#160;&#160; TreeNode *pRoot;<br />&#160;&#160;&#160; int nCount;<br />};<br />preview 的写法为：<br />preview (<br />&#160;&#160;&#160; #(<br />&#160;&#160;&#160; #tree(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; head: $e.pRoot,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; left: pLeft,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; right: Right,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; size: $e.nCount<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) : $e.nData // 注意，这里的 $e 代表 TreeNode，上面两个 $e 都代表 Tree<br />&#160;&#160;&#160; )<br />)</p> <p><br />preview 的格式就到此。接下来是 children，它用于描述点击变量左边的加号后，展开的内容怎么显示，如图：</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_10.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_thumb_4.png" width="199" height="119"></a></p> <p>IDE 会依次显示 children(#( … )) 括号内的以逗号分隔的内容，每个显示为一行。刚才的 #array, #list, #tree 都可以用，会显示成第一列索引第二列值的样子。<br />另外可以用 #(first, second) 的格式，first 会原样显示在第一列，second 会求值显示在第二列。</p> <p>&#160;</p> <p>了解以上这些内容，我们已经可以针对 STL 的那些数据结构做自定义显示了，对一些别的数据结构作简单的自定义显示也不难。</p> <p>&#160;</p> <p>最后给个效果图，定义了我自己的那些容器的显示方式。怎么样，看上去一定比开头给出的那个冷冰冰的样子好很多吧？</p> <p><a href="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.cppblog.com/images/cppblog_com/Streamlet/Windows-Live-Writer/f42585ce8478_E196/image_thumb_2.png" width="751" height="503"></a></p>]]></description>
		<wfw:commentRss>http://www.streamlet.org/archives/2011/02/28/177/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

