﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Forich</title><link>http://www.cppblog.com/Rich-cw/</link><description>探索未知</description><language>zh-cn</language><lastBuildDate>Thu, 23 Apr 2026 10:13:49 GMT</lastBuildDate><pubDate>Thu, 23 Apr 2026 10:13:49 GMT</pubDate><ttl>60</ttl><item><title>to be continue</title><link>http://www.cppblog.com/Rich-cw/archive/2010/01/05/104864.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Tue, 05 Jan 2010 13:51:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2010/01/05/104864.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/104864.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2010/01/05/104864.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/104864.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/104864.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp; 迫切地想要写点什么，却不知从何开头。这些天看的东西很杂，看《c++模板元编程》看得头大，看《深入浅出ATL》苦于无法实践，做题也没心思，又纠结于快要结课的考试。罢了，静心潜修才是正道。但总得提炼一下这混乱的思想，不然&#8220;脑黄金&#8221;就要随着&#8220;豆腐沙&#8221;被时间的潮水冲走了。先拟个题目，待考试一完就来补上。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <font size=4><strong>杂项：boost mpl 中的迭代器、算法与其它。</strong></font></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 题目有点大，只能尽力研究源码，尽量多写。好，目标在此，留待再议。</p>
<img src ="http://www.cppblog.com/Rich-cw/aggbug/104864.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2010-01-05 21:51 <a href="http://www.cppblog.com/Rich-cw/archive/2010/01/05/104864.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一些图</title><link>http://www.cppblog.com/Rich-cw/archive/2009/12/30/104489.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Wed, 30 Dec 2009 13:19:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2009/12/30/104489.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/104489.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2009/12/30/104489.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/104489.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/104489.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很久以前处于一种百无聊赖的状态做的图，先存这。<br><img border=0 src="http://www.cppblog.com/images/cppblog_com/rich-cw/12657/o_心情_thumb.gif"><br><img border=0 src="http://www.cppblog.com/images/cppblog_com/rich-cw/12657/o_Persistence%20was%20damned.jpg"><br><img border=0 src="http://www.cppblog.com/images/cppblog_com/rich-cw/12657/o_风_夏天.jpg"><br><br><img border=0 src="http://www.cppblog.com/images/cppblog_com/rich-cw/12657/o_充电器MR.jpg"><br><br><img border=0 src="http://www.cppblog.com/images/cppblog_com/rich-cw/12657/o_MyCup.jpg" width=604 height=604><br><br><img border=0 src="http://www.cppblog.com/images/cppblog_com/rich-cw/12657/o_MyCup1.jpg" width=640 height=400><br>
<img src ="http://www.cppblog.com/Rich-cw/aggbug/104489.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2009-12-30 21:19 <a href="http://www.cppblog.com/Rich-cw/archive/2009/12/30/104489.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TopCoder 练习题之排列（Permutation）</title><link>http://www.cppblog.com/Rich-cw/archive/2009/12/19/103543.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Sat, 19 Dec 2009 12:53:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2009/12/19/103543.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/103543.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2009/12/19/103543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/103543.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/103543.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp; 题目及解题程序给在末尾，先来看看排列一个数组的方法。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp; 给定一个数组 array[] = {3, 1, 2, 4, 0}; 这个给定的数组有目的性，即它符合 n * m 的规则，这里是 5 * 5（5个元素，5个连续且不同的值）。按我想到的一般的方法，就是使用循环来求出各种排列的可能，但这种方法不能确保每个元素只出现一次，且随着元素个数的增长，循环深度将变得很深。继续想下去，这种方法将会变得很复杂，这就要求我寻找另外一种方法。注意到每个元素并不相同，那么要使各个元素在每个位置上只出现一次，很明显的一种方法就是“彩票机读票法”。比如数据读入口在第一个元素的位置，那么依次循环这个数组，每次使后面的元素向前移动一位，各个数字不就都读到了吗，这就像在打印机中滚动的纸。具体步骤如下：</p> <p>31240<br>12403 &lt;—rotate  <p>&nbsp;&nbsp;&nbsp;&nbsp; 第一位如此，那么后面的每一位也如此，也就是递归地处理后面的数字，每移动一位就以下一位为起点做相同的处理，直到所有数字循环了一遍，那排列的工作也就完成了。一个具体的实现如下：<pre class="code"><span style="color: green">/*
 * @param r:     需要求其排列的向量
 * @param iPos:  当前所进行到的位置
 * 程序体中的注释表示处于那个位置的向量都是一个新的且唯一的排列
*/</span></pre><pre class="code"><span style="color: green"></span><span style="color: blue">void </span>rotate(vector&lt;<span style="color: blue">int</span>&gt;&amp; r, <span style="color: blue">int </span>iPos) {

    <span style="color: blue">if</span>(iPos == r.size() - 1)<span style="color: green">//是否循环完毕，调用函数时 iPos 置0
        </span><span style="color: blue">return</span>;

    <span style="color: blue">int </span>iNextPos = iPos + 1;
    <span style="color: blue">for</span>(size_t i = iPos; i &lt; r.size(); ++i) {
        <span style="color: blue">if</span>(i == 0) {
            <span style="color: green">//a different permutation, do something here
        </span>}

        <span style="color: blue">int </span>t = r[iPos];
        <span style="color: blue">for</span>(size_t j = iPos; j &lt; r.size() - 1; ++j)<span style="color: green">//循环前移
            </span>r[j] = r[j + 1];
        r[r.size() - 1] = t;

        <span style="color: blue">if</span>(i != r.size() - 1) {
            <span style="color: green">//a different permutation, do something here
        </span>}

        rotate(r, iNextPos);<span style="color: green">//从下一位数字开始新的位移
    </span>}
}</pre><a href="http://11011.net/software/vspaste"></a><pre class="code">   这种方法不要求数字式连续的，也不用事先规定好向量的长度。只是当向量长度到了一定的时候，运算时间会很长！其它方法未知……</pre><pre class="code">   topcoder 上的练习题如下：</pre>
<p>Problem Statement 
<p>A permutation A[0], A[1], ..., A[N-1] is a sequence containing each integer between 0 and N-1, inclusive, exactly once. Each permutation A of length N has a corresponding child array B of the same length, where B is defined as follows:<br>B[0] = 0<br>B[i] = A[B[i-1]], for every i between 1 and N-1, inclusive.<br>A permutation is considered perfect if its child array is also a permutation.&nbsp; Below are given all permutations for N=3 with their child arrays. Note that for two of these permutations ({1, 2, 0} and {2, 0, 1}) the child array is also a permutation, so these two permutations are perfect.<br>Permutation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Child array<br>{0, 1, 2}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0, 0, 0}<br>{0, 2, 1}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0, 0, 0}<br>{1, 0, 2}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0, 1, 0}<br>{1, 2, 0}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0, 1, 2}<br>{2, 0, 1}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0, 2, 1}<br>{2, 1, 0}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0, 2, 0}<br>You are given a vector &lt;int&gt; P containing a permutation of length N. Find a perfect permutation Q of the same length such that the difference between P and Q is as small as possible, and return this difference. The difference between P and Q is the number of indices i for which P[i] and Q[i] are different.<br>Definition 
<p>Class:<br>PerfectPermutation<br>Method:<br>reorder<br>Parameters:<br>vector &lt;int&gt;<br>Returns:<br>int<br>Method signature:<br>int reorder(vector &lt;int&gt; P)<br>(be sure your method is public) 
<p>Constraints<br>-<br>P will contain between 1 and 50 elements, inclusive.<br>-<br>P will contain each integer between 0 and N-1, inclusive, exactly once, where N is the number of elements in P.<br>Examples 
<p>0)<br>{2, 0, 1}<br>Returns: 0<br>P is a perfect permutation, so we can use the same permutation for Q. The difference is then 0 because P and Q are the same. 
<p>1)<br>{2, 0, 1, 4, 3}<br>Returns: 2<br>Q might be {2, 0, 3, 4, 1}. 
<p>2)<br>{2, 3, 0, 1}<br>Returns: 2<br>Q might be {1, 3, 0, 2}. 
<p>3)<br>{0, 5, 3, 2, 1, 4}<br>Returns: 3 
<p>4)<br>{4, 2, 6, 0, 3, 5, 9, 7, 8, 1}<br>Returns: 5 
<p>This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.</p>&nbsp;&nbsp;&nbsp; 我的解答如下：<pre class="code"><span style="color: blue">#include </span><span style="color: #a31515">&lt;iostream&gt;
</span><span style="color: blue">#include </span><span style="color: #a31515">&lt;vector&gt;
</span><span style="color: blue">#include </span><span style="color: #a31515">&lt;cstddef&gt;
</span><span style="color: blue">#include </span><span style="color: #a31515">&lt;limits&gt;
</span><span style="color: blue">#include </span><span style="color: #a31515">&lt;cassert&gt;

</span><span style="color: blue">#include </span><span style="color: #a31515">&lt;boost\assign.hpp&gt;    </span><span style="color: green">// for vector +=

</span><span style="color: blue">using namespace </span>std;

<span style="color: blue">class </span>PerfectPermutation {
<span style="color: blue">public</span>:
    <span style="color: blue">int  </span>reorder(<span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; P, vector&lt;<span style="color: blue">int</span>&gt;&amp; result);
    <span style="color: blue">bool </span>isPerfect(<span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; P);

<span style="color: blue">private</span>:
    <span style="color: blue">int  </span>difference(<span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; P, <span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; Q);
    <span style="color: blue">void </span>rotate(<span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; src, vector&lt;<span style="color: blue">int</span>&gt;&amp; r, <span style="color: blue">int </span>level, <span style="color: blue">int</span>&amp; nMin, vector&lt;<span style="color: blue">int</span>&gt;&amp; out);
};

<span style="color: blue">int </span>PerfectPermutation::difference(<span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; P, <span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; Q) {

    size_t cDiff = P.size();
    assert(cDiff == Q.size());

    <span style="color: blue">for</span>(size_t i = 0; i &lt; P.size(); ++i) {
        <span style="color: blue">if</span>(P[i] == Q[i])
            cDiff--;
    }

    <span style="color: blue">return </span>cDiff;
}

<span style="color: blue">bool </span>PerfectPermutation::isPerfect(<span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; A) {

    <span style="color: blue">int </span>Bi = 0, Bi_1 = 0;
    vector&lt;<span style="color: blue">bool</span>&gt; vb(A.size());
    vb[0] = <span style="color: blue">true</span>;

    <span style="color: blue">for</span>(size_t i = 1; i &lt; A.size(); ++i) {
        <span style="color: blue">if</span>(vb[Bi = A[Bi_1]])
            <span style="color: blue">return false</span>;
        <span style="color: blue">else
            </span>vb[Bi] = <span style="color: blue">true</span>;

        Bi_1 = Bi;
    }

    <span style="color: blue">return true</span>;
}

<span style="color: blue">void </span>PerfectPermutation::rotate(<span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; src, vector&lt;<span style="color: blue">int</span>&gt;&amp; r, <span style="color: blue">int </span>level, <span style="color: blue">int</span>&amp; nMin, vector&lt;<span style="color: blue">int</span>&gt;&amp; out) {

    <span style="color: blue">if</span>(level == r.size() - 1)
        <span style="color: blue">return</span>;

    <span style="color: blue">int </span>in = level + 1;
    <span style="color: blue">for</span>(size_t i = level; i &lt; r.size(); ++i) {
        <span style="color: blue">if</span>(i == 0 &amp;&amp; isPerfect(r)) {
            nMin = min(difference(src, r), nMin);
            out = r;
        }

        <span style="color: blue">int </span>t = r[level];
        <span style="color: blue">for</span>(size_t j = level; j &lt; r.size() - 1; ++j)
            r[j] = r[j + 1];
        r[r.size() - 1] = t;

        <span style="color: blue">if</span>((i != r.size() - 1) &amp;&amp; isPerfect(r)) {
            nMin = min(difference(src, r), nMin);
            out = r;
        }

        rotate(src, r, in, nMin, out);
    }
}

<span style="color: blue">int </span>PerfectPermutation::reorder(<span style="color: blue">const </span>vector&lt;<span style="color: blue">int</span>&gt;&amp; P, vector&lt;<span style="color: blue">int</span>&gt;&amp; result) {

    <span style="color: blue">if</span>(P.size() == 1 || isPerfect(P))
        <span style="color: blue">return </span>0;

    <span style="color: blue">int </span>nMin = numeric_limits&lt;<span style="color: blue">int</span>&gt;::max();

    vector&lt;<span style="color: blue">int</span>&gt; Q(P);

    rotate(P, Q, 0, nMin, result);

    <span style="color: blue">return </span>nMin == numeric_limits&lt;<span style="color: blue">int</span>&gt;::max() ? -1 : nMin;
}
<span style="color: blue">int </span>main() {

    <span style="color: blue">using namespace </span>boost::assign;

    PerfectPermutation pp;

    vector&lt;<span style="color: blue">int</span>&gt; P;
    P += 2, 0, 1, 4, 3;
    vector&lt;<span style="color: blue">int</span>&gt; result(P.size());

    cout &lt;&lt; <span style="color: #a31515">"Is a perfect Permutation :                    " </span>&lt;&lt; (pp.isPerfect(P) ? <span style="color: #a31515">"Yes" </span>: <span style="color: #a31515">"No"</span>) &lt;&lt; endl;
    cout &lt;&lt; <span style="color: #a31515">"Difference between before reorder and after : " </span>&lt;&lt; pp.reorder(P, result) &lt;&lt; endl;
    assert(pp.isPerfect(result));
    cout &lt;&lt; <span style="color: #a31515">"One answer might be :                         "</span>;
    <span style="color: blue">for</span>(size_t i = 0; i &lt; result.size(); ++i)
        cout &lt;&lt; result[i] &lt;&lt; <span style="color: #a31515">" "</span>;
    cout &lt;&lt; endl;

    <span style="color: blue">return </span>0;
}</pre><a href="http://11011.net/software/vspaste"></a><img src ="http://www.cppblog.com/Rich-cw/aggbug/103543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2009-12-19 20:53 <a href="http://www.cppblog.com/Rich-cw/archive/2009/12/19/103543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>整理几个offset</title><link>http://www.cppblog.com/Rich-cw/archive/2009/12/12/103059.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Sat, 12 Dec 2009 07:16:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2009/12/12/103059.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/103059.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2009/12/12/103059.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/103059.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/103059.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这几个 offset 是：</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c 中的 <font color="#ff0000">offsetof</font> 宏；</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 《COM本质论》: "inttable.h" 中的 <font color="#ff0000">BASE_OFFSET</font> ；</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 和 <font color="#ff0000">This()</font> (它用到了 offsetof，权且当做是一个 packaged offset 吧)。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先定义一些辅助类：</p><pre class="code"><span style="color: blue">struct </span>IX {
    <span style="color: blue">virtual void </span>fx() = 0;
};
<span style="color: blue">struct </span>IY {
    <span style="color: blue">virtual void </span>fy() = 0;
};
<span style="color: blue">class </span>CA : <span style="color: blue">public </span>IX,
           <span style="color: blue">public </span>IY {
<span style="color: blue">public</span>:
    <span style="color: blue">virtual void </span>fx() { cout &lt;&lt; <span style="color: #a31515">"CA::fx()" </span>&lt;&lt; endl; };
    <span style="color: blue">virtual void </span>fy() { cout &lt;&lt; <span style="color: #a31515">"CA::fy()" </span>&lt;&lt; endl; };

    <span style="color: blue">struct </span>Inner {
        CA* This() { <span style="color: blue">return </span>(CA*)((char*)<span style="color: blue">this </span>- offsetof(CA, m_inner)); }
    };
    Inner m_inner;
};</pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先看 offsetof ：</p><pre class="code"><span style="color: blue">#define </span>offsetof(s,m)   (size_t)&amp;<span style="color: blue">reinterpret_cast</span>&lt;<span style="color: blue">const volatile char</span>&amp;&gt;((((s *)0)-&gt;m))</pre><pre class="code">    工作原理大体同下图所示，其值就是 a – 0 = a ，即 m 被映射后的地址。所以一个 –&gt; 操作就可以搞定。</pre><pre class="code"><a href="http://www.cppblog.com/images/cppblog_com/Rich-cw/WindowsLiveWriter/offset_C57F/offset_2.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="offset" border="0" alt="offset" src="http://www.cppblog.com/images/cppblog_com/Rich-cw/WindowsLiveWriter/offset_C57F/offset_thumb.jpg" width="352" height="150"></a> </pre><pre class="code">    再看 BASE_OFFSET ：</pre><pre class="code"><span style="color: blue">#define </span>BASE_OFFSET(ClassName, BaseName) \
    (DWORD(<span style="color: blue">static_cast</span>&lt;BaseName*&gt;(<span style="color: blue">reinterpret_cast</span>&lt;ClassName*&gt;(0x10000000))) - 0x10000000)</pre><a href="http://11011.net/software/vspaste"></a>
<p>&nbsp;&nbsp;&nbsp; 对于先前的定义，有：</p>
<p>DWORD disX = BASE_OFFSET(CA, IX);<br>DWORD disY = BASE_OFFSET(CA, IY);<br>cout &lt;&lt; disX &lt;&lt; endl&nbsp;&nbsp;&nbsp; <span style="color: green">// 0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;&lt; disY &lt;&lt; endl;&nbsp;&nbsp; <span style="color: green">// 4</span></p>
<p>&nbsp;&nbsp;&nbsp; 这个宏主要利用了派生类指针到基类指针的转换，这一切由语言内置的转换符完成。在 ATL 中相应的定义是：</p><pre class="code"><span style="color: blue">#define </span>offsetofclass(base, derived) ((DWORD_PTR)(<span style="color: blue">static_cast</span>&lt;base*&gt;((derived*)_ATL_PACKING))-_ATL_PACKING)</pre><a href="http://11011.net/software/vspaste"></a>
<p>&nbsp;&nbsp;&nbsp; 其中 _ATL_PACKING 的值为 8 。为什么使用这两个值呢，我不知道。网上有说是为了避免 NULL 指针和负值，我暂时不能够理解。</p>
<p>&nbsp;&nbsp;&nbsp; 最后来看 This() ：</p><pre class="code">CA* This() { <span style="color: blue">return </span>(CA*)((BYTE*)<span style="color: blue">this </span>- offsetof(CA, Inner)); }</pre><pre class="code">    This() 返回的即是指向 CA 的指针，如： ca.m_inner.This()-&gt;fx(); 有了上面两个 offset ，这个就不难理解了。</pre><pre class="code">    整理完毕。</pre><a href="http://11011.net/software/vspaste"></a><img src ="http://www.cppblog.com/Rich-cw/aggbug/103059.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2009-12-12 15:16 <a href="http://www.cppblog.com/Rich-cw/archive/2009/12/12/103059.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>typedef 关键字二三事</title><link>http://www.cppblog.com/Rich-cw/archive/2009/12/09/102864.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Wed, 09 Dec 2009 13:20:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2009/12/09/102864.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/102864.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2009/12/09/102864.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/102864.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/102864.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 记得在看《windows 核心编程》第二十五章的 Spreadsheet 示例程序时，我对其中 <span style="color: blue">typedef </span>的用法很是困惑。当时翻看了《Big c++》（我的第一本 c++ 书籍），很可惜，上面讲得很简单，不足以解答我的疑惑。不知为什么当时没有坚持去解决那个问题，一直到现在才想起来对 <span style="color: blue">typedef </span>做个全面的回顾。STL 和 BOOST 为我们呈现了众多精彩的应用，<span style="color: blue">typedef </span>功不可没。先看看 《c++ primer》 怎么说的：</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Introduces a synonym for some other type. Form:</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为某种类型引入同义词。格式：</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">typedef </span>type synonym;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; defines synonym as another name for the type named type.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 定义 synonym 为名为 type 的类型的另一名字。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在看《核》一书的时候，我的了解就这么一点。为什么我看不懂呢？看看《核》中的用法：</p><pre class="code"><span style="color: blue">const int </span>g_nNumRows = 256;
<span style="color: blue">const int </span>g_nNumCols = 1024;

<span style="color: blue">typedef struct </span>{
    DWORD dwValue;
    BYTE  bDummy[1020];
} CELL, *PCELL;

<span style="color: blue">typedef </span>CELL SPREADSHEET[g_nNumRows][g_nNumCols];
<span style="color: blue">typedef </span>SPREADSHEET *PSPREADSHEET;</pre><pre class="code">    按照当时的想法，句子 SPREADSHEET[g_nNumRows][g_nNumCols] sh 的意思应该是 CELL sh ，不就该是这样的吗（因为它只是个别名/马甲）？但在我那个想法里 sh 可不是数组，所以我当时无法理解 sh 后来的行为。形式主义，对，形式主义影响了我，当时我就一彻底的形式主义者。我还想再一遍地重复这个词，不过那也太给它面子了。算了， Not worth to fight!(哈，最近看的一部精彩的家庭喜剧中的台词。这部剧名叫《the middle》)。《核》一书中接下来还有一个精彩的用法，为了简化代码，我把它写成这个样子：</pre><pre class="code"><span style="color: blue">class </span>Base {
<span style="color: blue">public</span>:
    <span style="color: blue">virtual </span>~Base();
    <span style="color: blue">void </span>fn();
    ...
<span style="color: blue">private</span>:
    <span style="color: blue">int </span>n;
};

<span style="color: blue">class </span>Derive : <span style="color: blue">public </span>Base {
    ...
    <span style="color: green">//no data member allow, just function here.
</span>};</pre><pre class="code"><span style="color: blue">static </span>Derive g_ssObject;
SPREADSHEET&amp; g_ss = *(PSPREADSHEET)(PCELL)g_ssObject;</pre><pre class="code">    如此一来，g_ss 就有了 Base 的 n 成员和 256 * 1024 个 CELL 结构。当向 Derive 对象使用 [] 时（它是 SPREADSHEET&amp; 型），它的行为就跟数组一致了（n 成员不会索引到，这也是不允许派生类有数据成员的原因）。关于它的内存并没有在它声明的时候开辟，以及后来怎么开辟，那就是另一个冒险故事了。这种手法让我再一次为《核》这本书所折服。</pre><pre class="code">    好了，回到 <span style="color: blue">typedef 。</span>我见得最多的用法不外乎 <span style="color: blue">typedef int </span>value_type ，“取绰号”是他的职责所在，我不能只把它理解为：当你看到 B（ value_type ） 时，它只不过是 A （ <font color="#0000ff">int</font> ），还要把它理解为像上面提到的一样：SPREADSHEET 并不只是一个 CELL ，而是多个 CELL 组成的 Array 的首个元素的位置指针，不然后面的两个跟屁虫双胞胎 “[][]” 作何解释。我的这种想法让我想起了 ATL 中的 OLECHAR ，在那里我也曾是个形式主义者（又重复了一遍！）。OLECHAR 在特定的平台上有特定的意义，比如在 windows 平台并定义了 UNICODE 的情况下，它是 <span style="color: blue">wchar_t </span>。如果保持这种理解，将无法把它当做一种特别的类型，从而在语言层面上有了障碍，也就违背了 OLECHAR 生来是为 COM 组件做“特殊”服务的本意。我们要把它当做基本类型看待，至于怎么看待以及详细的方法，另一个冒险故事…… 所以，“取绰号”专家的内涵并不单薄，我不能一厢情愿的认为他只是个爱捉弄人的讨厌鬼，它正经起来可也是一表人才滴。下面是一些 <span style="color: blue">typedef </span>的用法（来自《c++模板元编程》中某习题的解答）：</pre><pre class="code"><span style="color: blue">class </span>foo {...};

<span style="color: blue">typedef int </span>(foo::*pmd);    <span style="color: green">// pmd 解释为：指向 foo 数据成员的指针，返回值为 int
</span><span style="color: blue">typedef int </span>(foo::*pmf)();  <span style="color: green">// pmf 解释为：指向 foo 函数成员的指针，返回值为 int
</span><span style="color: blue">typedef int </span>(*pfunc)();     <span style="color: green">// pfunc 解释为：指向函数的指针，返回值为 int 且无参数（有参数的也就不难想象了）
</span><span style="color: blue">typedef const int</span>&amp; refc;    <span style="color: green">// 不说这个了</span></pre><pre class="code"><span style="color: green"></span></pre>&nbsp;&nbsp;&nbsp; 上面的展示非常不全面，网上总结的东西一大堆，我不能偷懒引用，去看才实在。不过有了这些知识，理解其它东西应该足够了。 <img src ="http://www.cppblog.com/Rich-cw/aggbug/102864.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2009-12-09 21:20 <a href="http://www.cppblog.com/Rich-cw/archive/2009/12/09/102864.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost 中的 vector 及其 operator+=</title><link>http://www.cppblog.com/Rich-cw/archive/2009/12/09/102837.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Wed, 09 Dec 2009 03:01:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2009/12/09/102837.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/102837.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2009/12/09/102837.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/102837.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/102837.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp; 在看 《c++ 模板元编程》 的过程中，我时时刻刻都会有新发现。对于这之前从未接触过 Boost 库的我来说，惊奇的感觉尤甚。初看此书的习题4-5：哈，不就是实现一个 param_type 嘛。的确是，不过 answer 页上的测试代码，才是让我惊奇的东西：</p><pre class="code"><span style="color: blue">using namespace </span>boost::assign;
std::vector&lt;<span style="color: blue">int</span>&gt; v1;
v1 += 1, 2, 30, 40, 500;</pre><pre class="code">   话不多讲，按图索骥的来分析。既然是 vector 的操作，那就找出对应的头文件来看看。第一句使用了 boost::assign 命名空间，而 STL 库中当然不会提供这样的 operator+= ，果然在 boost\assign\std\vector.hpp 中有声明：</pre><pre class="code"><span style="color: blue">template</span>&lt; <span style="color: blue">class </span>V, <span style="color: blue">class </span>A, <span style="color: blue">class </span>V2 &gt;
<span style="color: blue">inline </span>list_inserter&lt; assign_detail::call_push_back&lt; std::vector&lt;V,A&gt; &gt;, V &gt; 
<span style="color: blue">operator</span>+=( std::vector&lt;V,A&gt;&amp; c, V2 v ) {
    <span style="color: blue">return </span>push_back( c )( v );
}</pre><pre class="code">    For the god’s sake ，它一口气抛给我这么多待查的东西，这不是打击我的求知欲么！（歇息片刻……）继续。先不管这个重载操作符的返回值，待会在函数的返回语句中自然会了解到。看到 push_back( c )( v ) 这个句子，当然是一个 operator()，继续搜索。这一次，VS 代码查看工具直接把我带到了目的地—— boost\assign\list_inserter.hpp 这块新大陆。接下来的一切都将在这里发生。首先我到了 “push_back 站”：</pre><pre class="code"><span style="color: blue">template</span>&lt; <span style="color: blue">class </span>C &gt;
<span style="color: blue">inline </span>list_inserter&lt; assign_detail::call_push_back&lt;C&gt;, 
                      BOOST_DEDUCED_TYPENAME C::value_type &gt;
push_back( C&amp; c ) {
    <span style="color: blue">static </span>BOOST_DEDUCED_TYPENAME C::value_type* p = 0;<span style="color: green">//static typename std::vector&lt;int&gt;::value_type* p = 0;</span>
    <span style="color: blue">return </span>make_list_inserter( assign_detail::call_push_back&lt;C&gt;( c ), p );
}</pre><pre class="code">    为了方便查看，把 make_list_inserter 和 call_push_back 也列出来：</pre><pre class="code"><span style="color: blue">template</span>&lt; <span style="color: blue">class </span>Function, <span style="color: blue">class </span>Argument &gt;
<span style="color: blue">inline </span>list_inserter&lt;Function,Argument&gt;
make_list_inserter( Function fun, Argument* ) {
    <span style="color: blue">return </span>list_inserter&lt;Function, Argument&gt;( fun );
}</pre><pre class="code"><span style="color: blue">template</span>&lt; <span style="color: blue">class </span>C &gt;
<span style="color: blue">class </span>call_push_back {
    C&amp; c_;  <span style="color: green">//这里，c_ 是 vector&lt;int&gt;&amp; v1</span>
<span style="color: blue">public</span>:
    call_push_back( C&amp; c ) : c_( c ) { }
    
    <span style="color: blue">template</span>&lt; <span style="color: blue">class </span>T &gt;
    <span style="color: blue">void operator</span>()( T r ) {
        c_.push_back( r );
    }
};</pre><a href="http://11011.net/software/vspaste"></a><pre class="code">    过了这条流水线，现在 operator+= 中的 push_back( c ) 就被加工成了：</pre><pre class="code">    list_inserter&lt;call_push_back, p&gt;( call_push_back&lt;vector&lt;int&gt; &gt; ) ，其私有成员 insert_ 为 call_push_back&lt;vector&lt;int&gt; &gt; 。前面提到的 operator() 就要登场了，先看 list_inserter 的部分代码：</pre><pre class="code"><span style="color: blue">template</span>&lt; <span style="color: blue">class </span>Function, <span style="color: blue">class </span>Argument = assign_detail::forward_n_arguments &gt; 
<span style="color: blue">class </span>list_inserter {
    <font color="#0000ff">...</font>  
<span style="color: blue">public</span>:
    list_inserter( Function fun ) : insert_( fun ) {}    
    <span style="color: blue">...</span></pre><pre class="code"><span style="color: blue">    </span>list_inserter&amp; <span style="color: blue">operator</span>()() {    <span style="color: green">//这就是那个 operator() ! 终于找到你了</span>
        insert_( Argument() );
        <span style="color: blue">return </span>*<span style="color: blue">this</span>;
    }
    ...    
    <span style="color: blue">template</span>&lt; <span style="color: blue">class </span>T &gt;
    list_inserter&amp; <span style="color: blue">operator</span>,( <span style="color: blue">const </span>T&amp; r ) { <span style="color: green">//它化腐朽为神奇，逗号(,)从以前的“路标”升级成了“交警”</span></pre><pre class="code"><span style="color: green">        </span>insert_( r  );
        <span style="color: blue">return </span>*<span style="color: blue">this</span>;
    }</pre><pre class="code">    ... ...</pre><pre class="code"><span style="color: blue">private</span>:   
    list_inserter&amp; <span style="color: blue">operator</span>=( <span style="color: blue">const </span>list_inserter&amp; );
    Function insert_;  <span style="color: green">// call_push_back</span></pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><pre class="code">};</pre><pre class="code">    到这里，第一个 v1 += 1 就是下面这个样子：</pre><pre class="code">    list_inserter&lt;call_push_back, p&gt;( call_push_back&lt;vector&lt;int&gt; &gt; )( 1 )</pre><pre class="code">    相当于 call_push_back(1)，call_push_back的 c_ 成员就是 v1 的引用，就相当于 v1.push_back(1) 。第一个元素进入了容器，鼓掌。</pre><pre class="code">    看过代码后，逗号（ , ）就不足为奇了， v1 += 1, 2, 30, 40, 500; 句子中的 “,”， 功能是依次插入逗号后的元素。</pre><pre class="code">    继续探索新大陆……</pre><img src ="http://www.cppblog.com/Rich-cw/aggbug/102837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2009-12-09 11:01 <a href="http://www.cppblog.com/Rich-cw/archive/2009/12/09/102837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost 中的 and_ 如何实现短路（short-circuit behavior）</title><link>http://www.cppblog.com/Rich-cw/archive/2009/12/08/102787.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Tue, 08 Dec 2009 03:36:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2009/12/08/102787.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/102787.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2009/12/08/102787.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/102787.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/102787.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 它是用递归实现的。首先看下面的句子：</p><pre class="code">mpl::and_&lt;exp1, exp2&gt;
</pre><pre class="code">    它使用的是头文件中的模板:
</pre><pre class="code">mpl::and_&lt;exp1, exp2, true_, true_, true_&gt;
           1_    2_     3_    4_      5_
</pre><pre class="code">    然后这个模板继承自：
</pre><pre class="code">aux::and_impl&lt;
              BOOST_MPL_AUX_NESTED_TYPE_WKND(exp1)::value,
              exp2, 3_, 4_, 5_
             &gt;
</pre><pre class="code">    若 1_ 的 value 为 <span style="color: blue">false </span>，它就终结于下面的主模板：
<span style="color: blue"></span></pre><pre class="code"><span style="color: blue">template</span>&lt; <span style="color: blue">bool </span>C_, <span style="color: blue">typename </span>T1, <span style="color: blue">typename </span>T2, <span style="color: blue">typename </span>T3, <span style="color: blue">typename </span>T4 &gt;
<span style="color: blue">struct </span>and_impl
    : false_ {};
</pre><pre class="code">    否则，继续前进：</pre><pre class="code">aux::and_impl&lt;
              BOOST_MPL_AUX_NESTED_TYPE_WKND(exp2)::value,
              3_, 4_, 5_, true_
             &gt;
</pre><pre class="code">    这又回到了上一步的分叉路口。多个参数的情况与此类似。当全部参数都成 ture/true_ 时，就有了这个特化版本：</pre><pre class="code"><span style="color: blue">template</span>&lt;&gt;
<span style="color: blue">struct </span>and_impl&lt;
          <span style="color: blue">true
        </span>, true_, true_, true_, true_
        &gt;
    : true_ {};</pre><pre class="code">    这样一来，当前一个参数为 false 时，后面的参数就不用触及 ::value ，也就不会被实例化，这就是 short-circuit behavior，类似于 ||, &amp;&amp; 等操作符。 </pre><pre class="code">    同理可推知 or_ 的行为。</pre><img src ="http://www.cppblog.com/Rich-cw/aggbug/102787.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2009-12-08 11:36 <a href="http://www.cppblog.com/Rich-cw/archive/2009/12/08/102787.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Little thing about boost::mpl::if_</title><link>http://www.cppblog.com/Rich-cw/archive/2009/12/07/102747.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Mon, 07 Dec 2009 12:47:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2009/12/07/102747.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/102747.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2009/12/07/102747.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/102747.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/102747.html</trackback:ping><description><![CDATA[<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这本来没什么好说的，不过我在强啃了一天《c++ 模板元编程》这本书后，头脑昏沉，反应迟钝。也借整理 boost::mpl::if_ 这个让我查阅半天源码的小东西的机会，让自己放松一下。</p> <p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if_ 就是借 if_c 定义了自己 ::type 的一个元函数。之所以我会对 if_ 迷糊，是因为我想当然的认为 if_ 模板的第一个参数类型为 bool 值。这是受了 if 关键字的影响，也有错误理解 if_c 的原因。且看 if_c 的声明：</p><pre class="code"><span style="color: blue">template</span>&lt;
      <span style="color: blue">bool </span>C          <span style="color: green">// yeah, the type here is bool, but...
    </span>, <span style="color: blue">typename </span>T1
    , <span style="color: blue">typename </span>T2
    &gt;
<span style="color: blue">struct </span>if_c {
    <span style="color: blue">typedef </span>T1 type;
};

<span style="color: blue">template</span>&lt;            <span style="color: green">// 特化版本，类似这样定义元函数的例子很多
      </span><span style="color: blue">typename </span>T1
    , <span style="color: blue">typename </span>T2
    &gt;
<span style="color: blue">struct </span>if_c&lt;<span style="color: blue">false</span>,T1,T2&gt; {
    <span style="color: blue">typedef </span>T2 type;
};</pre><pre class="code">  既生 if_c ，何生 if_ ？对比二者的代码，if_ 比 if_c 多了如下句子：BOOST_MPL_AUX_LAMBDA_SUPPORT(3,if_,(T1,T2,T3))。而在 MSVC（VS2008） 编译器上这个句子没起作用。那它就是为了兼容编译器而生的，就名字来看和 lambda 表达式的支持性有关系。关于其他编译器的事情，我不知道，先搁置一边。再看 if_ 的声明：</pre><pre class="code"><span style="color: blue">template</span>&lt;
      <span style="color: blue">typename </span>BOOST_MPL_AUX_NA_PARAM(T1)
    , <span style="color: blue">typename </span>BOOST_MPL_AUX_NA_PARAM(T2)
    , <span style="color: blue">typename </span>BOOST_MPL_AUX_NA_PARAM(T3)
    &gt;
<span style="color: blue">struct </span>if_ {
 <span style="color: blue">private</span>:
    <span style="color: green">// agurt, 02/jan/03: two-step 'type' definition for the sake of aCC 
    </span><span style="color: blue">typedef </span>if_c&lt;
<span style="color: blue">#if defined</span>(BOOST_MPL_CFG_BCC_INTEGRAL_CONSTANTS)
          BOOST_MPL_AUX_VALUE_WKND(T1)::value
<span style="color: blue">#else
          </span>BOOST_MPL_AUX_STATIC_CAST(<span style="color: blue">bool</span>, BOOST_MPL_AUX_VALUE_WKND(T1)::value)
<span style="color: blue">#endif
        </span>, T2
        , T3
        &gt; almost_type_;
 
 <span style="color: blue">public</span>:
    <span style="color: blue">typedef typename </span>almost_type_::type type;
    BOOST_MPL_AUX_LAMBDA_SUPPORT(3,if_,(T1,T2,T3))
};</pre><pre class="code">    这就很明了了，先用 if_c 确定应该使用 T2 还是 T3，再来个迂回的定义，就成了 ::type 。所以就声明来看，if_ 的第一个模板参数确实是要求类型。初看时，我郁闷了，如果我喜欢用 value （有些习惯连自己也感到奇怪！），那我为什么不用 if_c 呢？哈，当然可以，如书上的例子：</pre><pre class="code"><span style="color: blue">template </span>&lt;<span style="color: blue">typename </span>T&gt;
<span style="color: blue">struct </span>param_type 
    : mpl::if_&lt;
               <span style="color: blue">typename </span>boost::is_scalar&lt;T&gt;::type,
               T,
               <span style="color: blue">typename </span>boost::add_reference&lt;T <span style="color: blue">const</span>&gt;::type
    &gt; {};
<span style="color: blue">typedef </span>param_type&lt;<span style="color: blue">float</span>&gt;::type float_;</pre><pre class="code">    完全可以改为：</pre><pre class="code"><span style="color: blue">template </span>&lt;<span style="color: blue">typename </span>T&gt;
<span style="color: blue">struct </span>param_type 
    : mpl::if_c&lt;
                boost::is_scalar&lt;T&gt;::value,
                T,
                <span style="color: blue">typename </span>boost::add_reference&lt;T <span style="color: blue">const</span>&gt;::type
    &gt; {};</pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 对于书上面的后几个简化，也照样适用。我就更郁闷了，我前几十分钟干嘛去了？死抓着 if_ 不放，不考虑试试其它可能。我想起了昨天对书上某个例子的扩充，确实受用（这当然不是说作者坏话，他是为了使书写得清晰明了才不使用在我看来是优化的东西的。呃，有点长…），我才再一次责怪起自己的读书习惯。古人云：尽信书不如无书。这句话用到这里就是：别死跟着书走（哪里跟哪里嘛，风马牛不相及，哈哈！）。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 关于 boost ，我不了解的太多，需要一步一步来，就从简单的开始吧。现在它可是远远超出了我的理解范围，希望能赶上一点是一点。</p><img src ="http://www.cppblog.com/Rich-cw/aggbug/102747.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2009-12-07 20:47 <a href="http://www.cppblog.com/Rich-cw/archive/2009/12/07/102747.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Inside Com》小结（一）</title><link>http://www.cppblog.com/Rich-cw/archive/2009/12/05/102618.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Sat, 05 Dec 2009 12:16:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2009/12/05/102618.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/102618.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2009/12/05/102618.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/102618.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/102618.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前不久看完了《Inside Com》。书写得非常棒，有了这个基础，打算继续研究《Com&nbsp; 本质论》。下面是我看完此书记录下来的一些东西：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. CoCreateInstance 的调用过程(这里的组件位于 DLL 中)：</p>
<p><a href="http://www.cppblog.com/images/cppblog_com/Rich-cw/WindowsLiveWriter/InsideCom_12C2C/CoCreateInstance_4.jpg"><img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=CoCreateInstance border=0 alt=CoCreateInstance src="http://www.cppblog.com/images/cppblog_com/Rich-cw/WindowsLiveWriter/InsideCom_12C2C/CoCreateInstance_thumb_1.jpg" width=504 height=337></a> </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图片说明了一切。对比一下 CoCreateInstance 的声明：</p>
<pre class=code>WINOLEAPI CoCreateInstance(__in        REFCLSID    rclsid,
__in_opt    LPUNKNOWN   pUnkOuter,
__in        DWORD       dwClsContext,
__in        REFIID      riid,
__deref_out LPVOID FAR* ppv);</pre>
<pre class=code>    值得一提的是 CoGetClassObject 调用了 Dll 的导出函数 DllGetClassObject ，Regsvr32 /s /u 当然是使用了对应的 DllRegisterServer / DllUnregisterServer 导出函数。如果使用 ATL，这一切繁杂的工作都省却了，但反注册还需手动操作&#8230;&#8230;</pre>
<pre class=code>    2. 获取聚合组件接口的过程：</pre>
<pre class=code>    理解组件聚合技术是一次痛苦的经历。前后三天，苦苦思索，我终于在那个阴冷的下午获得了&#8220;安东尼达斯&#8221;的垂青。如果他早一点给我一瓶智力药水，何至如此呢！看图说话：</pre>
<pre class=code><a href="http://www.cppblog.com/images/cppblog_com/Rich-cw/WindowsLiveWriter/InsideCom_12C2C/aggrgation_2.jpg"><img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=aggrgation border=0 alt=aggrgation src="http://www.cppblog.com/images/cppblog_com/Rich-cw/WindowsLiveWriter/InsideCom_12C2C/aggrgation_thumb.jpg" width=754 height=259></a> </pre>
<a href="http://11011.net/software/vspaste"></a>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中，两个InUnk都是非代理IUnknown。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样一来，对于外部组件来说：</p>
<table border=0 cellSpacing=0 cellPadding=2 width=248>
    <tbody>
        <tr>
            <td vAlign=top width=34>&nbsp;</td>
            <td vAlign=top width=25>IX</td>
            <td vAlign=top width=187>&nbsp; Outer-&gt;QueryInterface</td>
        </tr>
        <tr>
            <td vAlign=top width=34>获取</td>
            <td vAlign=top width=25>&nbsp;</td>
            <td vAlign=top width=187>&nbsp;</td>
        </tr>
        <tr>
            <td vAlign=top width=34>&nbsp;</td>
            <td vAlign=top width=25>IY</td>
            <td vAlign=top width=187>&nbsp; InUnkO-&gt;QueryInterface</td>
        </tr>
    </tbody>
</table>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于内部组件来说:</p>
<table border=0 cellSpacing=0 cellPadding=2 width=435>
    <tbody>
        <tr>
            <td vAlign=top width=34>&nbsp;</td>
            <td vAlign=top width=25>IX</td>
            <td vAlign=top width=374>&nbsp; OutUnk-&gt;QueryInterface-&gt;InUnkO-&gt;QueryInterface</td>
        </tr>
        <tr>
            <td vAlign=top width=34>获取</td>
            <td vAlign=top width=25>&nbsp;</td>
            <td vAlign=top width=374>&nbsp;</td>
        </tr>
        <tr>
            <td vAlign=top width=34>&nbsp;</td>
            <td vAlign=top width=25>IY</td>
            <td vAlign=top width=374>&nbsp; OutUnk-&gt;QueryInterface</td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有的 QueryInterface 动作都直接或间接的由外部组件执行。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这让我想起了《变形金刚2》。假如我一进电影院就睡着了，等到天火和擎天柱组合之后我才醒来。那么对于我来说，擎天柱就是外部组件，IX为跑。天火为内部组件，IY为飞。此时我不知道有天火的存在。当我问擎天柱你会飞吗的时候，他知道他不会飞（没有IY接口），于是他问天火你会不会飞，天火就返回IY（飞）接口，于是擎天柱告诉我他会飞。当他飞着的时候（我想通过IY来查询IX），我问他会跑么，这句话只有天火听得见（因为我用的是IY接口），天火不会跑，他就问擎天柱，擎天柱知道自己会跑（有IX接口），于是就给我一个IX接口。整个过程中，我只知道擎天柱，并不知道天火的存在，于是擎天柱聚合了天火。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但我怎么可能进去就睡着了呢！</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 内部组件的代理接口只是简单的调用外部的QueryInterface，是个转发站，一切工作交由外部组件统筹。关于具体实现，《COM本质论》中给出的 "impunk.h" 头文件中有很好的实现。我非常喜欢其中关于接口查找表的实现，那个offset获取偏移地址的方法让我这个C语言功力薄弱的人感到十分惭愧。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 过两天再把套间线程和自由线程整理出来。</p>
<img src ="http://www.cppblog.com/Rich-cw/aggbug/102618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2009-12-05 20:16 <a href="http://www.cppblog.com/Rich-cw/archive/2009/12/05/102618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Boost 中的 BOOST_STATIC_ASSERT</title><link>http://www.cppblog.com/Rich-cw/archive/2009/12/04/102530.html</link><dc:creator>崇文</dc:creator><author>崇文</author><pubDate>Fri, 04 Dec 2009 05:05:00 GMT</pubDate><guid>http://www.cppblog.com/Rich-cw/archive/2009/12/04/102530.html</guid><wfw:comment>http://www.cppblog.com/Rich-cw/comments/102530.html</wfw:comment><comments>http://www.cppblog.com/Rich-cw/archive/2009/12/04/102530.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/Rich-cw/comments/commentRss/102530.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Rich-cw/services/trackbacks/102530.html</trackback:ping><description><![CDATA[<pre class="code"><span style="color: blue"><font color="#000000" face="宋体">先看定义在头文件中的语句：</font></span></pre><pre class="code"><span style="color: blue">template </span>&lt;<span style="color: blue">bool </span>x&gt; <span style="color: blue">struct </span>STATIC_ASSERTION_FAILURE;

<span style="color: blue">template </span>&lt;&gt; <span style="color: blue">struct </span>STATIC_ASSERTION_FAILURE&lt;<span style="color: blue">true</span>&gt; { <span style="color: blue">enum </span>{ value = 1 }; };
<span style="color: green">
</span><span style="color: blue">template</span>&lt;<span style="color: blue">int </span>x&gt; <span style="color: blue">struct </span>static_assert_test{};

<span style="color: green">…</span></pre><pre class="code"><span style="color: green">使用的是显示转换</span></pre><pre class="code"><span style="color: green">// Note that the argument to the assert is explicitly cast to bool using old-
// style casts: <font color="#ff0000">too many compilers currently have problems with static_cast</font>
// when used inside integral constant expressions.</span></pre><pre class="code"><span style="color: green">…</span></pre><pre class="code"><span style="color: blue">#elif defined</span>(BOOST_MSVC)
<span style="color: blue">#define </span>BOOST_STATIC_ASSERT( B ) \
   <span style="color: blue">typedef </span>::boost::static_assert_test&lt;\
      <span style="color: blue">sizeof</span>(::boost::STATIC_ASSERTION_FAILURE&lt; (<span style="color: blue">bool</span>)( B ) &gt;)&gt;\ <font color="#008000">// ***********</font>
         BOOST_JOIN(boost_static_assert_typedef_, __COUNTER__)</pre><pre class="code"><font face="Verdana">关键的地方在于 <span style="color: blue">sizeof</span>() 中的句子。当 (<span style="color: blue">bool</span>)( B ) 为 false 时，因为没有这个特化版本，编译器将报错，如</font></pre><pre class="code"><font face="Verdana">《<b>Beyond the C++ Standard Library: An Introduction to Boost</b>》中所述：</font></pre><pre>Error: use of undefined type<br>  'boost::STATIC_ASSERTION_FAILURE&lt;false&gt;'</pre><pre>BOOST_JOIN(X, Y) 最终解释为 X##Y。__COUNTER__ 在 MSDN 中的描述：</pre><pre>Expands to an integer starting with 0 and incrementing by 1 every time it is used in a compiland.</pre><pre>每使用一次它就增1。</pre><img src ="http://www.cppblog.com/Rich-cw/aggbug/102530.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Rich-cw/" target="_blank">崇文</a> 2009-12-04 13:05 <a href="http://www.cppblog.com/Rich-cw/archive/2009/12/04/102530.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>