<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Van's House : C++</title><link>http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx</link><description>Tags: C++</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Inline or Not Inline</title><link>http://blogs.msdn.com/xiangfan/archive/2009/11/26/inline-or-not-inline.aspx</link><pubDate>Thu, 26 Nov 2009 05:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9928951</guid><dc:creator>xiangfan</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9928951.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9928951</wfw:commentRss><description>&lt;P&gt;What is inline? This keyword is&amp;nbsp;mainly used to ask the compiler&amp;nbsp;to inline substitution of the function body at the point of call. Like 'register', this is only a suggestion to the compiler. Modern compiler can handle inlining using advanced heuristic to get better size / performance balance without the suggestion from the developer. So most of the time, it is&amp;nbsp;unnecessary to use this keyword.&lt;/P&gt;
&lt;P&gt;Then what else? Here is the whole story of inline.&lt;/P&gt;
&lt;P&gt;Besides the suggestion to the compiler, inline keyword will also have some side effects.&lt;/P&gt;
&lt;P&gt;Assuming&amp;nbsp;I have defined a function 'f' in header file and include the header&amp;nbsp;in two different files: a.cpp and b.cpp. Like:&lt;/P&gt;
&lt;P&gt;void f() {}&lt;/P&gt;
&lt;P&gt;You'll get the following error when compiling (cl a.cpp b.cpp):&lt;/P&gt;
&lt;P&gt;b.obj : error LNK2005: "void __cdecl f(void)" (?f@@YAXXZ) already defined in a.obj&lt;BR&gt;a.exe : fatal error LNK1169: one or more multiply defined symbols found&lt;/P&gt;
&lt;P&gt;However, if you change the definition of f to:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;inline&lt;/STRONG&gt; void f() {}&lt;/P&gt;
&lt;P&gt;The compilation will succeed.&lt;/P&gt;
&lt;P&gt;Here&amp;nbsp;are the words from the standard:&lt;/P&gt;
&lt;P&gt;Every program shall contain exactly one definition of every non-inline function or object that is used in that program. An inline function shall be defined in every translation unit in which it is used.&lt;/P&gt;
&lt;P&gt;This is the fundamental difference between using or not using inline. That means inline functions can be defined multiple times in different translation unit (assuming they have exactly the same definition in every case), but it will also cause the so-called "inline-explosion" because the definition has to be duplicated.&lt;/P&gt;
&lt;P&gt;A function defined within a class definition is an inline function. If you don't want to duplicate the definition&amp;nbsp;everywhere, it is better to move&amp;nbsp;the definition&amp;nbsp;into a separate&amp;nbsp;cpp. &lt;A href="http://msdn.microsoft.com/en-us/library/xbf3tbeh.aspx" mce_href="http://msdn.microsoft.com/en-us/library/xbf3tbeh.aspx"&gt;/LTCG&lt;/A&gt; can still inline it if appropriate.&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9928951" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category></item><item><title>Detect Shift Overflow</title><link>http://blogs.msdn.com/xiangfan/archive/2009/06/13/detect-shift-overflow.aspx</link><pubDate>Sat, 13 Jun 2009 08:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9742030</guid><dc:creator>xiangfan</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9742030.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9742030</wfw:commentRss><description>&lt;P&gt;This is an intellectual exercise: when shifts a 32-bit unsigned integer in C++, how to detect whether the calculation overflows efficiently?&lt;/P&gt;
&lt;P&gt;Here is the function prototype. shl_overflow will return true if v &amp;lt;&amp;lt; cl overflows (cl is between 0 and 31. And we assume that sizeof(unsigned long) == 4 and sizeof(unsigned long long) == 8).&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;bool&lt;/SPAN&gt; shl_overflow(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt; v, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; cl)&lt;/P&gt;
&lt;P&gt;The most natural way to implement this function is to extend v to 64-bit integer:&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;bool&lt;/SPAN&gt; shl_overflow(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt; v, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; cl)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt; vl = v;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; (vl &amp;lt;&amp;lt; cl &amp;gt;&amp;gt; 32) != 0;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;Now, let’s dig into the assembly world. We’ll limit the discussion on x86.&lt;BR&gt;&lt;BR&gt;mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, DWORD PTR _v$[esp-4]&lt;BR&gt;mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ecx, DWORD PTR _cl$[esp-4]&lt;BR&gt;xor&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; edx, edx&lt;BR&gt;call&amp;nbsp;&amp;nbsp;&amp;nbsp; __allshl&lt;BR&gt;xor&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, eax&lt;BR&gt;or&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, edx&lt;BR&gt;jne&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; overflow&lt;/P&gt;
&lt;P&gt;The implementation has to use three specific registers: eax, edx and ecx. And there is an expensive external function call.&lt;/P&gt;
&lt;P&gt;If you step into __allshl in the debugger, you can find that it will use shld to shift 64-bit integer. VC provides some intrinsics which map to CPU instructions. For example, __ll_lshift will map to shld.&lt;/P&gt;
&lt;P&gt;Because the high dword of vl is 0, we can simplify our code:&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;bool&lt;/SPAN&gt; shl_overflow(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt; v, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; cl)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt; vl = __ll_lshift(v, cl);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static_cast&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;FONT color=#0000ff&gt;long&lt;/FONT&gt;&amp;gt;(vl &amp;gt;&amp;gt; 32)) != 0;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;The assembly looks like:&lt;BR&gt;&lt;BR&gt;
&lt;P&gt;mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, DWORD PTR _v$[esp-4]&lt;BR&gt;mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ecx, DWORD PTR _cl$[esp-4]&lt;BR&gt;xor&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; edx, edx&lt;BR&gt;shld&amp;nbsp;&amp;nbsp;&amp;nbsp; edx, eax, cl&lt;BR&gt;test&amp;nbsp;&amp;nbsp;&amp;nbsp; edx&lt;BR&gt;jne&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; overflow&lt;/P&gt;
&lt;P&gt;Much better now.&lt;/P&gt;
&lt;P&gt;Another approach is based on bit representation.&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;bool&lt;/SPAN&gt; shl_overflow(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt; v, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; cl)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; v = _rotl(v, cl);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt; index;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; _BitScanForward(&amp;amp;index, v) ? index &amp;gt;= cl : &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;false&lt;/SPAN&gt;;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;The idea is simple. If v &amp;lt;&amp;lt; cl overflows, that means the most significant cl bits of v should contains "1".&lt;/P&gt;
&lt;P&gt;There are two ways to test that.&lt;/P&gt;
&lt;P&gt;1. Scan v from the least significant bits to the most, and test the index against 32 – cl. However, we have to handle the case when cl = 0.&lt;/P&gt;
&lt;P&gt;2. Rotate v cl bits left first, so the most significant cl bits will be the least significant cl bits. Then we can scan and test the index against cl directly.&lt;/P&gt;
&lt;P&gt;Notice that, the scan may fail if v is 0. The second way is simpler and more efficient.&lt;/P&gt;
&lt;P&gt;The assembly looks like:&lt;/P&gt;
&lt;P&gt;mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ecx, DWORD PTR _cl$[esp-4]&lt;BR&gt;mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, DWORD PTR _v$[esp-4]&lt;BR&gt;rol&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, cl&lt;BR&gt;bsf&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, eax&lt;BR&gt;je&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; notoverflow&lt;BR&gt;cmp&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eax, ecx&lt;BR&gt;jl&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; overflow&lt;/P&gt;
&lt;P&gt;It only uses two registers. It can also be extended to handle 64-bit shift. One drawback is an extra conditional jump (The extra jump can be replaced by "cmovz eax, ecx", but there is no way to ask the compiler to generate that)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9742030" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/VC/default.aspx">VC</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/Optimization/default.aspx">Optimization</category></item><item><title>Recursive Algorithm in C++</title><link>http://blogs.msdn.com/xiangfan/archive/2009/05/23/recursive-algorithm-in-c.aspx</link><pubDate>Sat, 23 May 2009 17:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9637398</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9637398.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9637398</wfw:commentRss><description>&lt;P&gt;Many recursive algorithms have initial parameters. For example, &lt;A href="http://mathworld.wolfram.com/FibonacciNumber.html" target=_blank mce_href="http://mathworld.wolfram.com/FibonacciNumber.html"&gt;Fibonacci Number&lt;/A&gt; is defined as: Fn = Fn-1 + Fn-2, with F1 = F2 = 1.&lt;/P&gt;
&lt;P&gt;By giving different values to F1 and F2, we can generate different sequence of numbers.&lt;/P&gt;
&lt;P&gt;1. If we implement the algorithm using functions, we have to either define these parameters as global variables or pass them in each recursive iteration.&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; Fib(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; n, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; f1, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; f2)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;if&lt;/SPAN&gt; (n &amp;lt; 1) &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; 0;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;if&lt;/SPAN&gt; (n &amp;gt;= 3) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; Fib(n - 1, f1, f2) + Fib(n - 2, f1, f2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;else&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;if&lt;/SPAN&gt; (n == 2) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; f2;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;else&lt;/SPAN&gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; f1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;2. Recursive functor can store the initial parameters as the class data member. Here is the example.&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; FibFunctor&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FibFunctor(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; f1, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; f2) : m_f1(f1), m_f2(f2) {}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; m_f1, m_f2;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;operator&lt;/SPAN&gt;()(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; n) &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;if&lt;/SPAN&gt; (n &amp;lt; 1) &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; 0;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;if&lt;/SPAN&gt; (n &amp;gt;= 3) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; (*&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;this&lt;/SPAN&gt;)(n - 1) + (*&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;this&lt;/SPAN&gt;)(n - 2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;else&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;if&lt;/SPAN&gt; (n == 2) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; m_f2;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;else&lt;/SPAN&gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; m_f1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; Fib(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; n, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; f1, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; f2)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FibFunctor f(f1, f2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; f(n);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;3. &lt;A href="http://blogs.msdn.com/vcblog/archive/2008/10/28/lambdas-auto-and-static-assert-c-0x-features-in-vc10-part-1.aspx" target=_blank mce_href="http://blogs.msdn.com/vcblog/archive/2008/10/28/lambdas-auto-and-static-assert-c-0x-features-in-vc10-part-1.aspx"&gt;Lambda&lt;/A&gt; is a new core language feature introduced in C++0x to define implicit function object. However, "this" is not valid inside lambda expression.&lt;/P&gt;
&lt;P&gt;This post &lt;A title="Visual C++ Team Blog - Stupid Lambda Tricks" href="http://blogs.msdn.com/vcblog/archive/2008/11/18/stupid-lambda-tricks.aspx" mce_href="http://blogs.msdn.com/vcblog/archive/2008/11/18/stupid-lambda-tricks.aspx"&gt;Visual C++ Team Blog - Stupid Lambda Tricks&lt;/A&gt; shows how to write a recursive lambda. So the above functor can be rewritten as:&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; Fib(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; n, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; f1, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; f2)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;auto&lt;/SPAN&gt; f = [&amp;amp;](&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; n) -&amp;gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;if&lt;/SPAN&gt; (n &amp;lt; 1) &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; 0;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;if&lt;/SPAN&gt; (n &amp;gt;= 3) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; f(n - 1) + f(n - 2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;else&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;if&lt;/SPAN&gt; (n == 2) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; f2;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;else&lt;/SPAN&gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; f1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt; f(n);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;Here, [&amp;amp;] is equivalent to [&amp;amp;f, &amp;amp;f1, &amp;amp;f2].&lt;/P&gt;
&lt;P&gt;(According to C++03 3.3.1/1: "The point of declaration for a name is immediately after its complete declarator and before its initializer (if any).", it is legal to capture f in the lambda expression. That means:&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; A {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A(A*);&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A a = A(&amp;amp;a); &lt;SPAN style="COLOR: rgb(0,128,0)"&gt;// OK&lt;/SPAN&gt;&lt;BR&gt;})&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9637398" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/VC/default.aspx">VC</category></item><item><title>Measure Initialization Time of Global Variables</title><link>http://blogs.msdn.com/xiangfan/archive/2009/05/12/measure-initialization-time-of-global-variables.aspx</link><pubDate>Tue, 12 May 2009 15:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9606987</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9606987.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9606987</wfw:commentRss><description>&lt;P&gt;&lt;STRONG&gt;NOTICE: The technique describes in the article may not be supported in future release of VC. You should not use it in production code&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;There are two kinds of initialization in C++: static initialization and dynamic initialization.&lt;/P&gt;
&lt;P&gt;According to the standard, static initialization shall always be performed before any dynamic initialization takes place.&lt;/P&gt;
&lt;P&gt;In VC, static initialization is done at compile time. The value is stored in the data section of the generated executable. On the other hand, dynamic initialization happens at runtime. Before entering main, CRT will call the dynamic initializers of the global variables.&lt;/P&gt;
&lt;P&gt;Sometimes you may need to measure the startup time of your program. However, dynamic initialization happens before main, so your measurement will not include it.&lt;/P&gt;
&lt;P&gt;This article "&lt;A href="http://msdn.microsoft.com/en-us/library/bb918180.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb918180.aspx"&gt;CRT Initialization&lt;/A&gt;" describes the detailed information of how dynamic initialization works in VC. &lt;/P&gt;
&lt;P&gt;VC provides pragma &lt;A href="http://msdn.microsoft.com/en-us/library/7977wcck.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/7977wcck.aspx"&gt;init_seg&lt;/A&gt; to fine-control the initialization process. It will place the dynamic initializers in the specific section. Besides predefined compiler, lib and user (the corresponding section names are ".CRT$XCC", ".CRT$XCL" and ".CRT$XCU"), you can also specify the section name explicitly.&lt;/P&gt;
&lt;P&gt;With these knowledge, we can use the following code to measure the initialization time of global variables.&lt;/P&gt;
&lt;P&gt;Let’s create two files: InitTime_Start.cpp and InitTime_End.cpp (we have to use two files because one file can only have one init_seg)&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;//InitTime_Start.cpp&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#pragma&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;warning&lt;/SPAN&gt;(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;disable&lt;/SPAN&gt; : 4075)&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#pragma&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;init_seg&lt;/SPAN&gt;(&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;".CRT$XCB"&lt;/SPAN&gt;)&lt;BR&gt;&lt;BR&gt;Timer gInitTimer;&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;//InitTime_End.cpp&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#pragma&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;warning&lt;/SPAN&gt;(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;disable&lt;/SPAN&gt; : 4075)&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#pragma&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;init_seg&lt;/SPAN&gt;(&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;".CRT$XCY"&lt;/SPAN&gt;)&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;double&lt;/SPAN&gt; gInitTime = gInitTimer.GetTime();&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Here, "Timer" is a class which will start timing in ctor and return the elapsed time in member function GetTime. Because ".CRT$XCB" will be placed before ".CRT$XCC", the dynamic initializer of the timer will be called before any dynamic initializers of compiler generated global variables. Similarly, gInitTimer.GetTime will be called after all the dynamic initializers of user defined global variables. Then "gInitTime" will contain the initialization time of all global variables including those generated by compiler, library and user.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9606987" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/VC/default.aspx">VC</category></item><item><title>Optimize Your Code: Matrix Multiplication</title><link>http://blogs.msdn.com/xiangfan/archive/2009/04/28/optimize-your-code-matrix-multiplication.aspx</link><pubDate>Tue, 28 Apr 2009 15:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9573500</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9573500.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9573500</wfw:commentRss><description>&lt;P&gt;Matrix multiplication is common and the algorithm is easy to implementation. Here is one example:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Version 1:&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; SeqMatrixMult1(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; size, T** m1, T** m2, T** result)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; size; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; j = 0; j &amp;lt; size; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result[i][j] = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; k = 0; k &amp;lt; size; k++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result[i][j] += m1[i][k] * m2[k][j];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;This implementation is straight-forward and you can find it in text book and many online samples.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Version 2:&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; SeqMatrixMult2(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; size, T** m1, T** m2, T** result)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; size; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; j = 0; j &amp;lt; size; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T c = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; k = 0; k &amp;lt; size; k++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c += m1[i][k] * m2[k][j];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result[i][j] = c;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;} &lt;/P&gt;
&lt;P&gt;This version will use a temporary to store the intermediate result. So we can save a lot of unnecessary memory write. Notice that the optimizer can not help here because it doesn't know whether "result" is an alias of "m1" or "m2".&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Version 3:&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; Transpose(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; size, T** m)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; size; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; j = i + 1; j &amp;lt; size; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; std::swap(m[i][j], m[j][i]);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; SeqMatrixMult3(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; size, T** m1, T** m2, T** result)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Transpose(size, m2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; size; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; j = 0; j &amp;lt; size; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T c = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; k = 0; k &amp;lt; size; k++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c += m1[i][k] * m2[j][k];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result[i][j] = c;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Transpose(size, m2);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;This optimization is tricky. If you profile the function, you'll find a lot of data cache miss. We transpose the matrix so that both m1[i] and m2[i] can be accessed sequentially. This can greatly improve the memory read performance.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Version 4:&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; SeqMatrixMult4(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; size, T** m1, T** m2, T** result);&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;// assume size % 2 == 0&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;// assume m1[i] and m2[i] are 16-byte aligned&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;// require SSE3 (haddpd)&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; SeqMatrixMult4(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; size, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;double&lt;/SPAN&gt;** m1, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;double&lt;/SPAN&gt;** m2, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;double&lt;/SPAN&gt;** result)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Transpose(size, m2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; size; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; j = 0; j &amp;lt; size; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;__m128d&lt;/SPAN&gt; c = _mm_setzero_pd();&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; k = 0; k &amp;lt; size; k += 2) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c = _mm_add_pd(c, _mm_mul_pd(_mm_load_pd(&amp;amp;m1[i][k]), _mm_load_pd(&amp;amp;m2[j][k])));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c = _mm_hadd_pd(c, c);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mm_store_sd(&amp;amp;result[i][j], c);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Transpose(size, m2);&lt;BR&gt;}&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;// assume size % 4 == 0&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;// assume m1[i] and m2[i] are 16-byte aligned&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;// require SSE3 (haddps)&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; SeqMatrixMult4(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; size, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;float&lt;/SPAN&gt;** m1, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;float&lt;/SPAN&gt;** m2, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;float&lt;/SPAN&gt;** result)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Transpose(size, m2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; size; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; j = 0; j &amp;lt; size; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;__m128&lt;/SPAN&gt; c = _mm_setzero_ps();&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; k = 0; k &amp;lt; size; k += 4) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c = _mm_add_ps(c, _mm_mul_ps(_mm_load_ps(&amp;amp;m1[i][k]), _mm_load_ps(&amp;amp;m2[j][k])));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c = _mm_hadd_ps(c, c);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c = _mm_hadd_ps(c, c);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mm_store_ss(&amp;amp;result[i][j], c);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Transpose(size, m2);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;For float types, we can use SIMD instruction set to parallel the data processing.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Parallel version using PPL (&lt;A href="http://msdn.microsoft.com/en-us/magazine/dd434652.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/magazine/dd434652.aspx"&gt;Parallel Patterns Library&lt;/A&gt;) and lambda in VC2010 CTP:&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; ParMatrixMult1(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; size, T** m1, T** m2, T** result)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;using&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;namespace&lt;/SPAN&gt; Concurrency;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; size; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parallel_for(0, size, 1, [&amp;amp;](&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; j) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result[i][j] = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; k = 0; k &amp;lt; size; k++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result[i][j] += m1[i][k] * m2[k][j];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Result&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Here are the test results (what really matters is the relative time between different version):&lt;/P&gt;
&lt;P&gt;Matrix size = 500 (Intel Core 2 Duo T7250, 2 cores, L2 cache 2MB)&lt;/P&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=2 width=600&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;int&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;long long&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;float&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;double&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 1&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.931119s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;2.945134s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.774894s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.984585s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 2&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.571003s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;2.310568s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.724161s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.929064s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 3&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.239538s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.823095s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.570772s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.241691s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 4&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;N/A&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;N/A&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.063196s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.187614s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 1 + PPL&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.847534s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;1.683765s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.589513s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.994161s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 2 + PPL&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.380174s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;1.190713s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.409321s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.594859s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 3 + PPL&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.135760s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.495152s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.370499s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.185800s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 4 + PPL&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;N/A&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;N/A&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.041959s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.157932s&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;Matrix size = 500 (Intel&amp;nbsp;Xeon E5430,&amp;nbsp;4 cores, L2 cache 12MB)&lt;/P&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=2 width=600&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;int&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;long long&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;float&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;double&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 1&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.514330s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;1.434509s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.455168s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.608127s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 2&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.314554s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;1.231696s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.447607s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.593517s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 3&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.180176s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.591002s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.432129s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.149511s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 4&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;N/A&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;N/A&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.042900s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.083286s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 1 + PPL&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.308766s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.482934s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.175585s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.309159s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 2 + PPL&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.105717s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.325413s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.124862s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.164156s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 3 + PPL&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.073418s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.193824s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.116971s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.061268s&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=120&gt;Version 4 + PPL&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;N/A&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;N/A&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.017891s&lt;/TD&gt;
&lt;TD vAlign=top width=120&gt;0.031734s&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;From the results, you can find that:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Parallelism only helps if you carefully tune your code to maximize its effect (Version 1)&lt;/LI&gt;
&lt;LI&gt;Eliminating unnecessary memory write (Version 2) helps the parallelism&lt;/LI&gt;
&lt;LI&gt;Data cache miss can be a big issue when there are lots of memory access (Version 3)&lt;/LI&gt;
&lt;LI&gt;Using SIMD instead of FPU on aligned data is beneficial (Version 4)&lt;/LI&gt;
&lt;LI&gt;Different data types, data sizes and host architectures may have different kinds of bottlenecks&lt;/LI&gt;&lt;/UL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9573500" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/Optimization/default.aspx">Optimization</category></item><item><title>C++ Template Trick: Detecting Object Slicing</title><link>http://blogs.msdn.com/xiangfan/archive/2009/03/22/c-template-trick-detecting-object-slicing.aspx</link><pubDate>Sun, 22 Mar 2009 17:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9498655</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9498655.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9498655</wfw:commentRss><description>&lt;P&gt;Object slicing often happens when you pass the object by value. Compiler will do implicitly conversion from derived to base for you without any warning message.&lt;/P&gt;
&lt;P&gt;If you want to detect object slicing, you're on your own. However, template can help you.&lt;/P&gt;
&lt;P&gt;Because object slicing will call copy constructor of base class, what you can do is to "hijack" it. The magic looks like:&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;&amp;lt;type_traits&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"boost\static_assert.hpp"&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;bool&lt;/SPAN&gt;&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; SliceHelper&lt;BR&gt;{&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; SliceHelper&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;false&lt;/SPAN&gt;&amp;gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typedef&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; type;&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; DETECTSLICE(NAME,SIZE)\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {_SizeOfClass=SIZE};\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; _SizeValidation() {BOOST_STATIC_ASSERT(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;sizeof&lt;/SPAN&gt;(NAME)==_SizeOfClass);}\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt; &amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T&amp;gt; NAME(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt; T &amp;amp;,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; SliceHelper&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;sizeof&lt;/SPAN&gt;(T)==_SizeOfClass || !std::tr1::is_base_of&amp;lt;NAME,T&amp;gt;::value&amp;gt;::type * = 0)\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typedef&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T::sliced type;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; A&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; a;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A() {}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DETECTSLICE(A,4)&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; B:&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt; A&lt;BR&gt;{&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; C:&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt; A&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; b;&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; D&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; a;&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; E&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; a,b;&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; f(A) {}&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; B b;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C c;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; D d;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; E e;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A a;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A a0(a);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A a1(b);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,128,0)"&gt;//A a2(c); //error&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,128,0)"&gt;//A a3(d); //error&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,128,0)"&gt;//A a4(e); //error&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; f(a);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; f(b);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,128,0)"&gt;//f(c); //error&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,128,0)"&gt;//f(d); //error&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,128,0)"&gt;//f(e); //error&lt;/SPAN&gt;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;Notice:&lt;/P&gt;
&lt;P&gt;1. The template constructor is not a copy constructor. According to the standard, copy constructor should be non-template. But the template constructor can still be chosen to copy construct the object :-)&lt;/P&gt;
&lt;P&gt;2. You can not use sizeof in the member function declaration because the class is incomplete at that point. You can only use sizeof inside the member function definition. That is why we have to specify the size of the class explicitly.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9498655" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category></item><item><title>C++ Template Trick: Detecting the Existence of Class Member at Compile Time</title><link>http://blogs.msdn.com/xiangfan/archive/2009/02/09/c-template-trick-detecting-the-existence-of-class-member-at-compile-time.aspx</link><pubDate>Mon, 09 Feb 2009 18:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9408785</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9408785.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9408785</wfw:commentRss><description>&lt;P&gt;C++0x will provide a full set of type traits helpers to ease generic programming. However, there is no support for the detection of class members. The general problem is hard. Here we will try to tackle the more specific version: detecting the class member with given name and type.&lt;/P&gt;
&lt;P&gt;In C++, function overload is one of the most widely used technique to implement type traits. However, function overload only cares about types. Default argument and access modifier are only considered after the overload resolution. What we want here is to find out whether the specific member exists. So we have to turn the member into the type. Fortunately, template supports non-type argument. And here is the magic:&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;namespace&lt;/SPAN&gt; van {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;namespace&lt;/SPAN&gt; type_traits {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;namespace&lt;/SPAN&gt; detail {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typedef&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;char&lt;/SPAN&gt; Small;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; Big {&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;char&lt;/SPAN&gt; dummy[2];}; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; Type,Type Ptr&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; MemberHelperClass;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; Type&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Small MemberHelper_f(MemberHelperClass&amp;lt;Type,&amp;amp;T::f&amp;gt; *);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; Type&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Big MemberHelper_f(...);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; Type&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; has_member_f&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {value=&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;sizeof&lt;/SPAN&gt;(detail::MemberHelper_f&amp;lt;T,Type&amp;gt;(0))==&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;sizeof&lt;/SPAN&gt;(detail::Small)};&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; A&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; f();&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; B&lt;BR&gt;{&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;&amp;lt;iostream&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;using&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;namespace&lt;/SPAN&gt; std;&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout&amp;lt;&amp;lt;boolalpha;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout&amp;lt;&amp;lt;van::type_traits::has_member_f&amp;lt;A,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; (*)()&amp;gt;::value&amp;lt;&amp;lt;endl;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout&amp;lt;&amp;lt;van::type_traits::has_member_f&amp;lt;B,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; (*)()&amp;gt;::value&amp;lt;&amp;lt;endl;&lt;BR&gt;}&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;If the member "f" is missing, the non-type (&amp;amp;T::f) to type (MemberHelperClass) conversion will be invalid, so the va-arg version will be chosen. Otherwise, the former will be chosen because the va-arg version is always the least preferable. Then has_member_f will distinguish these two cases by checking the size of the return value of the chosen MemberHelper_f function.&amp;nbsp;The above&amp;nbsp;code&amp;nbsp;supports both static members and non-static members. It also supports both data members and function members. However, it has one drawback. If the detected member is non-public, there will be&amp;nbsp;compiler error. That is because access control is applied after the overload resolution.&lt;/P&gt;
&lt;P&gt;Because the member name itself cannot be used as a template argument, we have to use it explicitly in our helper. To prevent the redundant work, we can take advantage of macro to get a more general version:&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; DEFINEHASMEMBER(Name)\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;namespace&lt;/SPAN&gt; van {\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;namespace&lt;/SPAN&gt; type_traits {\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;namespace&lt;/SPAN&gt; detail {\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; Type&amp;gt;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Small MemberHelper_##Name(MemberHelperClass&amp;lt;Type,&amp;amp;T::Name&amp;gt; *);\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; Type&amp;gt;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Big MemberHelper_##Name(...);\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }\&lt;BR&gt;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; Type&amp;gt;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; has_member_##Name\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {value=&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;sizeof&lt;/SPAN&gt;(detail::MemberHelper_##Name&amp;lt;T,Type&amp;gt;(0))==&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;sizeof&lt;/SPAN&gt;(detail::Small)};\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }\&lt;BR&gt;}&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;One usage of this type trait is to simplify dispatcher. For example, we want to provide different implementation for different architecture to get better performance. Instead of dispatch the code manually, we can automate the work using the member detection trait.&lt;/P&gt;
&lt;P&gt;First, we group the different implementations into one helper class.&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; MemoryCopyHelper&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typedef&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; (*FunctionType)(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; *lpDest, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; *lpSrc, size_t n);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; Default(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; *lpDest, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; *lpSrc, size_t n){}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; MMX(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; *lpDest, &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt; *lpSrc, size_t n){}&lt;BR&gt;};&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Second, we create the array to store the address of each implementation. If the implementation for some architecture is missing, we can use the default one instead (assume the default one is always present).&lt;BR&gt;&lt;BR&gt;DEFINEHASMEMBER(Default)&lt;BR&gt;DEFINEHASMEMBER(MMX)&lt;BR&gt;DEFINEHASMEMBER(SSE2)&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; DEFINESELECTSTATICMEMBER(MemberName)\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; FunType,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;bool&lt;/SPAN&gt; = van::type_traits::has_member_##MemberName&amp;lt;T,FunType&amp;gt;::value&amp;gt;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; select_member_##MemberName;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; FunType&amp;gt;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; select_member_##MemberName&amp;lt;T,FunType,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;true&lt;/SPAN&gt;&amp;gt; {&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt; FunType value;};\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; FunType&amp;gt;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; select_member_##MemberName&amp;lt;T,FunType,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;false&lt;/SPAN&gt;&amp;gt; {&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt; FunType value;};\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; FunType&amp;gt;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt; FunType select_member_##MemberName&amp;lt;T,FunType,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;true&lt;/SPAN&gt;&amp;gt;::value=&amp;amp;T::MemberName;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; T,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;typename&lt;/SPAN&gt; FunType&amp;gt;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt; FunType select_member_##MemberName&amp;lt;T,FunType,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;false&lt;/SPAN&gt;&amp;gt;::value=&amp;amp;T::Default;&lt;BR&gt;&lt;BR&gt;DEFINESELECTSTATICMEMBER(Default)&lt;BR&gt;DEFINESELECTSTATICMEMBER(MMX)&lt;BR&gt;DEFINESELECTSTATICMEMBER(SSE2)&lt;BR&gt;&lt;BR&gt;MemoryCopyHelper::FunctionType gDispatchArray_MemoryCopy[]={&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; select_member_Default&amp;lt;MemoryCopyHelper, MemoryCopyHelper::FunctionType&amp;gt;::value,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; select_member_MMX&amp;lt;MemoryCopyHelper, MemoryCopyHelper::FunctionType&amp;gt;::value,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; select_member_SSE2&amp;lt;MemoryCopyHelper, MemoryCopyHelper::FunctionType&amp;gt;::value,&lt;BR&gt;};&lt;/P&gt;
&lt;P&gt;Then you can focus on the implementation. You can update the helper class to add the optimized version for the missing architecture in the future. The array will be automatically updated. (Notice: the above array will be initialized dynamically before entering into main)&lt;/P&gt;
&lt;P&gt;BTW: The above code may fail on some old compilers. It is OK with VC8, VC9, gcc 3.4.5.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9408785" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category></item><item><title>Standard library changes in C++0x</title><link>http://blogs.msdn.com/xiangfan/archive/2009/01/12/standard-library-changes-in-c-0x.aspx</link><pubDate>Mon, 12 Jan 2009 17:22:10 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9307872</guid><dc:creator>xiangfan</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9307872.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9307872</wfw:commentRss><description>&lt;p&gt;C++0x will be released in the near future. Do you know the changes of standard library? Here is a list of changes that I've collected (minor behavior changes and changes related to concepts are not included).&lt;/p&gt; &lt;p&gt;1. New stuff&lt;/p&gt; &lt;p&gt;system_error:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new header&lt;br&gt;array, vector, deque, list, string, map, set, unordered_map, unordered_set:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new member function: cbegin, cend, crbegin, crend&lt;br&gt;vector, deque, string:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new member function: shrink_to_fit&lt;br&gt;map, unordered_map:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new member function: at&lt;br&gt;type_traits:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new traits:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; is_lvalue_reference, is_rvalue_reference&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; has_trivial_default_constructor, has_trivial_copy_constructor, has_nothrow_default_constructor, has_nothrow_copy_constructor&lt;br&gt;string:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new type: u16string, u32string&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new function:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stoi, stol, stoul, stoll, stoull, stof, stod, stold&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; to_string, to_wstring&lt;br&gt;algorithm:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new function:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; all_of, any_of, none_of, find_if_not, copy_if, partition_copy, is_partitioned, partition_point&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; minmax_element&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; is_heap_until, is_heap&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; is_sorted_until, is_sorted&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; next,prev&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; min,max,minmax&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; copy_n&lt;br&gt;random:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new class: seed_seq and many new distributions&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new function: generate_canonical&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new type:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ranlux24_base, ranlux48_base, ranlux24, ranlux48, knuth_b&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; default_random_engine&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; For classes linear_congruential, subtract_with_carry, mersenne_twister, discard_block, xor_combine:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; add ctor which accepts seed_seq, member function "seed" and the corresponding _engine class&lt;br&gt;memory:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new class: default_delete,unique_ptr&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new function: allocate_shared,make_shared&lt;br&gt;functional:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new functor: bit_and, bit_or, bit_xor&lt;br&gt;numeric:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new function: iota&lt;br&gt;iomanip:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new function:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get_money, put_money&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get_time, put_time&lt;br&gt;ios:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new function: defaultfloat&lt;br&gt;iosfwd:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new type: char_traits&amp;lt;char16_t&amp;gt;, char_traits&amp;lt;char32_t&amp;gt;&lt;br&gt;limits:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new member function: max_digits10, lowest &lt;/p&gt; &lt;p&gt;2. From tr1&lt;/p&gt; &lt;p&gt;array&lt;br&gt;unordered_map&lt;br&gt;unordered_set&lt;br&gt;regex&lt;br&gt;random&lt;br&gt;type_traits&lt;br&gt;tuple&lt;br&gt;functional&lt;br&gt;utility&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;br&gt;ios&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hexfloat  &lt;p&gt;3. Other&lt;/p&gt; &lt;p&gt;set, map, unordered_map, unordered_set:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; member function "erase" will have return value (compatible with sequential container)&lt;br&gt;string:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pop_back, front, back (compatible with vector)&lt;br&gt;bitset:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctor: unsigned long -&amp;gt; unsigned long long&lt;br&gt;fstream:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctor/open accept string &amp;amp; wstring as the type of filename (C++03 only supports raw string pointer)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9307872" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category></item><item><title>VC extensions list</title><link>http://blogs.msdn.com/xiangfan/archive/2008/12/11/vc-extensions-list.aspx</link><pubDate>Fri, 12 Dec 2008 01:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9198948</guid><dc:creator>xiangfan</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9198948.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9198948</wfw:commentRss><description>&lt;P&gt;MSDN has a &lt;A class="" href="http://msdn.microsoft.com/en-us/library/34h23df8(VS.80).aspx" mce_href="http://msdn.microsoft.com/en-us/library/34h23df8(VS.80).aspx"&gt;page&lt;/A&gt; describing various VC&amp;nbsp;extensions. But it is far from complete.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I've&amp;nbsp;collected&amp;nbsp;a list of nonstandard extensions&amp;nbsp;provided by VC, some of them are &lt;STRONG&gt;evil&lt;/STRONG&gt;.&amp;nbsp;If you want to&amp;nbsp;write standard conformant C++ code, you'd better be aware of these extensions which&amp;nbsp;are on by default. Some commonly (mis-)used extensions are in bold.&lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/f795hcch.aspx" mce_href="http://msdn.microsoft.com/en-us/library/f795hcch.aspx"&gt;W4001&lt;/A&gt;: nonstandard extension 'single line comment' was used&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/bacb5038.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bacb5038.aspx"&gt;W4152&lt;/A&gt;: nonstandard extension, function/data pointer conversion in expression&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/79wf64bc.aspx" mce_href="http://msdn.microsoft.com/en-us/library/79wf64bc.aspx"&gt;W4200&lt;/A&gt;: nonstandard extension used : zero-sized array in struct/union&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/c89bw853.aspx" mce_href="http://msdn.microsoft.com/en-us/library/c89bw853.aspx"&gt;W4201&lt;/A&gt;: nonstandard extension used : &lt;STRONG&gt;nameless struct/union&lt;/STRONG&gt;&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/9yzc6y3b.aspx" mce_href="http://msdn.microsoft.com/en-us/library/9yzc6y3b.aspx"&gt;W4202&lt;/A&gt;: nonstandard extension used : '...': prototype parameter in name list illegal&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/yax3f30x.aspx" mce_href="http://msdn.microsoft.com/en-us/library/yax3f30x.aspx"&gt;W4203&lt;/A&gt;: nonstandard extension used : union with static member variable&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/6b73z23c.aspx" mce_href="http://msdn.microsoft.com/en-us/library/6b73z23c.aspx"&gt;W4204&lt;/A&gt;: nonstandard extension used : non-constant aggregate initializer&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/7a94ekhs.aspx" mce_href="http://msdn.microsoft.com/en-us/library/7a94ekhs.aspx"&gt;W4205&lt;/A&gt;: nonstandard extension used : static function declaration in function scope&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/2xz1ww4k.aspx" mce_href="http://msdn.microsoft.com/en-us/library/2xz1ww4k.aspx"&gt;W4206&lt;/A&gt;: nonstandard extension used : translation unit is empty&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/h40wte08.aspx" mce_href="http://msdn.microsoft.com/en-us/library/h40wte08.aspx"&gt;W4207&lt;/A&gt;: nonstandard extension used : extended initializer form&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/x9z4waxa.aspx" mce_href="http://msdn.microsoft.com/en-us/library/x9z4waxa.aspx"&gt;W4208&lt;/A&gt;: nonstandard extension used : delete [exp] - exp evaluated but ignored&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/d8fs65w0.aspx" mce_href="http://msdn.microsoft.com/en-us/library/d8fs65w0.aspx"&gt;W4210&lt;/A&gt;: nonstandard extension used : function given file scope&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/88zaxt6c.aspx" mce_href="http://msdn.microsoft.com/en-us/library/88zaxt6c.aspx"&gt;W4211&lt;/A&gt;: nonstandard extension used : redefined extern to static&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/z4cahb0t.aspx" mce_href="http://msdn.microsoft.com/en-us/library/z4cahb0t.aspx"&gt;W4212&lt;/A&gt;: nonstandard extension used : function declaration used ellipsis&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/yshyhfby.aspx" mce_href="http://msdn.microsoft.com/en-us/library/yshyhfby.aspx"&gt;W4213&lt;/A&gt;: nonstandard extension used : cast on l-value&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/k7ea7ce7.aspx" mce_href="http://msdn.microsoft.com/en-us/library/k7ea7ce7.aspx"&gt;W4214&lt;/A&gt;: nonstandard extension used : bit field types other than int&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/00yasssw.aspx" mce_href="http://msdn.microsoft.com/en-us/library/00yasssw.aspx"&gt;W4215&lt;/A&gt;: nonstandard extension used : long float&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/477k4w1s.aspx" mce_href="http://msdn.microsoft.com/en-us/library/477k4w1s.aspx"&gt;W4216&lt;/A&gt;: nonstandard extension used : float long&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/2xye9y6s.aspx" mce_href="http://msdn.microsoft.com/en-us/library/2xye9y6s.aspx"&gt;W4218&lt;/A&gt;: nonstandard extension used : must specify at least a storage class or a type&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/d2719049.aspx" mce_href="http://msdn.microsoft.com/en-us/library/d2719049.aspx"&gt;W4221&lt;/A&gt;: nonstandard extension used : 'identifier' : cannot be initialized using address of automatic variable&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/81f5xs47.aspx" mce_href="http://msdn.microsoft.com/en-us/library/81f5xs47.aspx"&gt;W4223&lt;/A&gt;: nonstandard extension used : non-lvalue array converted to pointer&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/wh722488.aspx" mce_href="http://msdn.microsoft.com/en-us/library/wh722488.aspx"&gt;W4224&lt;/A&gt;: nonstandard extension used : formal parameter 'identifier' was previously defined as a type&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/7585wc3f.aspx" mce_href="http://msdn.microsoft.com/en-us/library/7585wc3f.aspx"&gt;W4226&lt;/A&gt;: nonstandard extension used : 'keyword' is an obsolete keyword&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/c5886yty.aspx" mce_href="http://msdn.microsoft.com/en-us/library/c5886yty.aspx"&gt;W4228&lt;/A&gt;: nonstandard extension used : qualifiers after comma in declarator list are ignored&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/9d0x3403.aspx" mce_href="http://msdn.microsoft.com/en-us/library/9d0x3403.aspx"&gt;W4231&lt;/A&gt;: nonstandard extension used : 'identifier' before template explicit instantiation&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/9a1sy630.aspx" mce_href="http://msdn.microsoft.com/en-us/library/9a1sy630.aspx"&gt;W4232&lt;/A&gt;: nonstandard extension used : 'identifier' : address of dllimport 'dllimport' is not static, identity not guaranteed&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/7ebe1389.aspx" mce_href="http://msdn.microsoft.com/en-us/library/7ebe1389.aspx"&gt;W4233&lt;/A&gt;: nonstandard extension used : 'keyword' keyword only supported in C++, not C&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/6zz25ez2.aspx" mce_href="http://msdn.microsoft.com/en-us/library/6zz25ez2.aspx"&gt;W4234&lt;/A&gt;: nonstandard extension used : 'keyword' keyword reserved for future use&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/7e5yy2kb.aspx" mce_href="http://msdn.microsoft.com/en-us/library/7e5yy2kb.aspx"&gt;W4235&lt;/A&gt;: nonstandard extension used : 'keyword' keyword not supported on this architecture&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/7zyb9yb4.aspx" mce_href="http://msdn.microsoft.com/en-us/library/7zyb9yb4.aspx"&gt;W4238&lt;/A&gt;: nonstandard extension used : &lt;STRONG&gt;class rvalue used as lvalue&lt;/STRONG&gt;&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/186yxbac.aspx" mce_href="http://msdn.microsoft.com/en-us/library/186yxbac.aspx"&gt;W4239&lt;/A&gt;: nonstandard extension used : 'token' : conversion from 'type' to 'type'&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/h2kd22yx.aspx" mce_href="http://msdn.microsoft.com/en-us/library/h2kd22yx.aspx"&gt;W4240&lt;/A&gt;: nonstandard extension used : access to 'classname' now defined to be 'access specifier', previously it was defined to be 'access specifier'&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/bk5hc10s.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bk5hc10s.aspx"&gt;W4288&lt;/A&gt;: nonstandard extension used : 'var' : loop control variable declared in the for-loop is used outside the for-loop scope; it conflicts with the declaration in the outer scope&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/06d758c0.aspx" mce_href="http://msdn.microsoft.com/en-us/library/06d758c0.aspx"&gt;W4289&lt;/A&gt;: nonstandard extension used : 'var' : loop control variable declared in the for-loop is used outside the for-loop scope&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/2a68558f.aspx" mce_href="http://msdn.microsoft.com/en-us/library/2a68558f.aspx"&gt;W4353&lt;/A&gt;: nonstandard extension used: constant 0 as function expression.&amp;nbsp; Use '__noop' function intrinsic instead&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/ms173702.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms173702.aspx"&gt;W4480&lt;/A&gt;: nonstandard extension used: specifying underlying type for enum 'enum'&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/ms173703.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms173703.aspx"&gt;W4481&lt;/A&gt;: nonstandard extension used: override specifier 'keyword'&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/ms173704.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms173704.aspx"&gt;W4482&lt;/A&gt;: nonstandard extension used: enum 'enum' used in qualified name&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/syzh26ty.aspx" mce_href="http://msdn.microsoft.com/en-us/library/syzh26ty.aspx"&gt;W4509&lt;/A&gt;: nonstandard extension used: 'function' uses SEH and 'object' has destructor&lt;BR&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/ms173717.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms173717.aspx"&gt;W4836&lt;/A&gt;: nonstandard extension used : &lt;STRONG&gt;'type' : local types or unnamed types cannot be used as template arguments&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/ft6cc9ha.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ft6cc9ha.aspx"&gt;C2599&lt;/A&gt;: &lt;STRONG&gt;'enum' : forward declaration of enum type is not allowed&lt;/STRONG&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9198948" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/VC/default.aspx">VC</category></item><item><title>Contiguousness of STL containers and string</title><link>http://blogs.msdn.com/xiangfan/archive/2008/12/04/contiguous-of-stl-containers-and-string.aspx</link><pubDate>Thu, 04 Dec 2008 08:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9173622</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9173622.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9173622</wfw:commentRss><description>&lt;P&gt;In C++, it is well-known that the data in the vector is contiguous. To be more specific, here is the quotation from the standard (C++03, 23.2.4/1)&lt;/P&gt;
&lt;P&gt;The elements of a vector are stored contiguously, meaning that if v is a vector&amp;lt;T, Allocator&amp;gt; where T is some type other than bool, then it obeys the identity &amp;amp;v[n] == &amp;amp;v[0] + n for all 0 &amp;lt;= n &amp;lt; v.size().&lt;/P&gt;
&lt;P&gt;There're two points. First, vector&amp;lt;bool&amp;gt; is special. It is optimized for size, and the bools are packed. Second, &amp;amp;v[0] is only valid if v.size() &amp;gt; 0.&lt;/P&gt;
&lt;P&gt;(BTW: The above statement doesn't exist in C++98. Here is the link to the history: &lt;A title=http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#69 href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#69" mce_href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#69"&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#69&lt;/A&gt;)&lt;/P&gt;
&lt;P&gt;vector is designed to be an advanced version of raw array, so the guarantee of contiguous is convenient when raw pointer is needed to pass to low level API. We can simply use v.empty()?NULL:&amp;amp;v[0] (if you use default allocator which implies that the return value of "operator []" is a real reference, not a proxy).&lt;/P&gt;
&lt;P&gt;In C++0x, it adds "data" member function for the similar purpose.&lt;/P&gt;
&lt;P&gt;In contrast, other containers in STL don't store data contiguously.&lt;/P&gt;
&lt;P&gt;string is a little different. It is not a STL container and standard doesn't explicitly say whether the data is contiguous. But it also provides "data" member function which returns "const charT *". Here is the definition in C++03:&lt;/P&gt;
&lt;P&gt;If size() is nonzero, the member returns a pointer to the initial element of an array whose first size() elements equal the corresponding elements of the string controlled by *this&lt;BR&gt;&lt;STRONG&gt;The program shall not alter any of the values stored in the array.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;On the other hand, it is also said that for "operator []"&lt;/P&gt;
&lt;P&gt;If pos &amp;lt; size(), returns data()[pos].&lt;/P&gt;
&lt;P&gt;Because "operator []" return reference, for string s, we have &amp;amp;s[0] == data(). However, data() is not modifiable according to the bold text above. It is also confusing that we can get non-const reference from data().&lt;/P&gt;
&lt;P&gt;There is a issue about whether string data is contiguous: &lt;A title=http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530 href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530" mce_href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530"&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Fortunately, it will be explicitly stated in C++0x, see &lt;A href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf" target=_blank mce_href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf"&gt;n2798.pdf&lt;/A&gt; 21.3.1/3:&lt;/P&gt;
&lt;P&gt;The char-like objects in a basic_string object shall be stored contiguously. That is, for any basic_string object s, the identity &amp;amp;*(s.begin() + n) == &amp;amp;*s.begin() + n shall hold for all values of n such that 0 &amp;lt;= n &amp;lt; s.size().&lt;/P&gt;
&lt;P&gt;The C++0x draft also changes "operator []", so it no longer relies on "data" (in fact, "data" will have the same behavior of c_str in C++0x):&lt;/P&gt;
&lt;P&gt;If pos &amp;lt; size(), returns *(begin() + pos).&lt;/P&gt;
&lt;P&gt;So, in C++0x, the data of string is guaranteed to be contiguous, and you can pass &amp;amp;s[0] (if s.size() &amp;gt; 0 and you use default allocator) to low level API like vector. Cheers!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9173622" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category></item><item><title>Protected or Private?</title><link>http://blogs.msdn.com/xiangfan/archive/2008/10/16/protected-or-private.aspx</link><pubDate>Thu, 16 Oct 2008 05:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9001360</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9001360.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9001360</wfw:commentRss><description>&lt;P&gt;As the designer of base class, you may hesitate whether to use private or protect access control. Then, let's try the following examples:&lt;/P&gt;
&lt;P&gt;1. Call protected member function&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;&amp;lt;cstdio&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt;&amp;nbsp;A&lt;BR&gt;{&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;protected&lt;/SPAN&gt;:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt;&amp;nbsp;b()&amp;nbsp;{printf(&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"Oops!\n"&lt;/SPAN&gt;);}&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt;&amp;nbsp;f(A*&amp;nbsp;a)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt;&amp;nbsp;A_hack:&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt;&amp;nbsp;A&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;friend&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt;&amp;nbsp;f(A*);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static_cast&lt;/SPAN&gt;&amp;lt;A_hack&amp;nbsp;*&amp;gt;(a)-&amp;gt;b();&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt;&amp;nbsp;B&lt;BR&gt;{&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt;:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt;&amp;nbsp;f(A*&amp;nbsp;a)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt;&amp;nbsp;A_hack:&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt;&amp;nbsp;A&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;friend&lt;/SPAN&gt;&amp;nbsp;B;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static_cast&lt;/SPAN&gt;&amp;lt;A_hack&amp;nbsp;*&amp;gt;(a)-&amp;gt;b();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt;&amp;nbsp;main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f(NULL);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;B().f(NULL);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;Although the result of the cast is undefined as stated in the standard, if no this pointer adjustment happens and the layout of A is the same as A_hack which are normally the case, the code will break the access control.&lt;/P&gt;
&lt;P&gt;For the evil user, his purpose is archieved.&lt;/P&gt;
&lt;P&gt;2. Call pure virtual function&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt;&amp;nbsp;A&lt;BR&gt;{&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;protected&lt;/SPAN&gt;:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;virtual&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt;&amp;nbsp;Fun()&amp;nbsp;=0;&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt;&amp;nbsp;B:&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt;&amp;nbsp;A&lt;BR&gt;{&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt;:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;B()&amp;nbsp;{Dummy();}&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;private&lt;/SPAN&gt;:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt;&amp;nbsp;Dummy()&amp;nbsp;{Fun();}&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt;&amp;nbsp;C:&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt;&amp;nbsp;B&lt;BR&gt;{&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt;:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;virtual&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt;&amp;nbsp;Fun()&amp;nbsp;{}&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt;&amp;nbsp;main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;C&amp;nbsp;c;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;Do you ever wonder how to call pure virtual function? Do you like to see what does _purecall in VC do? Just try the above code.&lt;/P&gt;
&lt;P&gt;The problem here is because of the protect access of "Fun" in base class. Of course, you should not call virtual function in ctor (they will not have polymorphic behavior), but when you call Dummy in ctor, you may not realize the fact that Dummy will call virtual function internally. Then the disaster happens.&lt;/P&gt;
&lt;P&gt;If what you want by using virtual is to allow the derived class to provide some specific behavior, you'd better declare the function as private.&lt;/P&gt;
&lt;P&gt;Although both the above code are nonconformant, they at least show the possibility that your user can do more than what you expect for protect.&lt;/P&gt;
&lt;P&gt;If you don't even have confidence with private (Like evil #define private public which definitely violates One Definition Rule), you'd better use the &lt;A class="" href="http://c2.com/cgi/wiki?PimplIdiom" mce_href="http://c2.com/cgi/wiki?PimplIdiom"&gt;PImpl Idiom&lt;/A&gt; to implement your interface.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9001360" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category></item><item><title>Obfuscate your code</title><link>http://blogs.msdn.com/xiangfan/archive/2008/09/16/obfuscate-your-code.aspx</link><pubDate>Wed, 17 Sep 2008 01:49:24 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8954499</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/8954499.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=8954499</wfw:commentRss><description>&lt;p&gt;Obfuscation is widely used to protect your code from reverse engineering.&lt;br&gt;Here is one example which takes advantage of indirected call and opcode overlap in X86:  &lt;p&gt;&lt;span style="color: rgb(0,0,255)"&gt;__declspec&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;naked&lt;/span&gt;)&lt;br&gt;&lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Fun1()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,0,255)"&gt;__asm &lt;/span&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,128,0)"&gt;//obfuscation chunk&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call LABEL1&lt;br&gt;LABEL1:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pop eax&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, 6&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; jmp eax&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,128,0)"&gt;//real function body&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;}&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style="color: rgb(0,0,255)"&gt;__declspec&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;naked&lt;/span&gt;)&lt;br&gt;&lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Fun2()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,0,255)"&gt;__asm&lt;/span&gt; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,128,0)"&gt;//obfuscation chunk&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call LABEL1&lt;br&gt;LABEL1:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pop eax&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; add eax, 7&lt;br&gt;&lt;span style="color: rgb(0,128,0)"&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; jmp -1&lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; jmp eax (merged with the previous instruction) 0xEB 0xFF 0xFF 0xE0 -&amp;gt; 0xEB 0xFF 0xE0&lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(0,128,0)"&gt;*/&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __emit 0xEB&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __emit 0xFF&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __emit 0xE0&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,128,0)"&gt;//real function body&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; main()&lt;br&gt;{&lt;br&gt;&lt;span style="color: rgb(0,0,255)"&gt;#if&lt;/span&gt; 0&lt;br&gt;&lt;span style="color: rgb(128,128,128)"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Fun1();&lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(0,0,255)"&gt;#else&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Fun2();&lt;br&gt;&lt;span style="color: rgb(0,0,255)"&gt;#endif&lt;/span&gt;&lt;br&gt;}&lt;br&gt; &lt;p&gt;In Fun1, the obfuscation chunk do the following work:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Get the current EIP (LABEL1) &lt;li&gt;Adjust the EIP to the target function &lt;li&gt;Jump to the target&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In Fun2, it merges the two jump instructions which will confuse the disassembler. To make the analysis even harder, we can rely on the fact that “add eax, 7” (assume the real function body is after our obfuscation chunk) will never overflow, and replace “jmp –1” with “jno -1”. Or we can use more complicated arithmetic to compute the target address.&lt;/p&gt; &lt;p&gt;Other kinds of obfuscations include:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;API Call Obfuscation (LoadLibrary+Encrypted Parameter)&lt;/li&gt; &lt;li&gt;Data Encryption (String Literal)&lt;/li&gt; &lt;li&gt;Code CheckSum + AntiDebugger&lt;/li&gt; &lt;li&gt;Dynamic Data Extraction&lt;/li&gt;&lt;/ul&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8954499" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/Reverse+Engineering/default.aspx">Reverse Engineering</category></item><item><title>Play with the C++ compiler - compile nightmare</title><link>http://blogs.msdn.com/xiangfan/archive/2008/09/15/play-with-the-c-compiler-compile-nightmare.aspx</link><pubDate>Mon, 15 Sep 2008 17:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8952632</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/8952632.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=8952632</wfw:commentRss><description>&lt;P&gt;Playing with the compiler is interesting. One challenge for the compiler writer is compilation performance. There're many kinds of C++ code which are the nightmare for the compiler. Now let's go! 
&lt;P&gt;1. Preprocess 
&lt;P&gt;a. Self Inclusion (GCC only)&lt;BR&gt;Normally, the compiler will limit the nest level of inclusion. In order to challenge the compiler, you have to stop the inclusion at appropriate stage. GCC provides a useful macro __INCLUDE_LEVEL__ to do the work.&lt;BR&gt;(We can write similar code for other compiler, although less elegant) 
&lt;P&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#if&lt;/SPAN&gt; __INCLUDE_LEVEL__&amp;lt;199&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt; __FILE__&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt; __FILE__&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#endif&lt;/SPAN&gt;&lt;BR&gt;
&lt;P&gt;b. Macro Expansion Explosion&lt;BR&gt;By using macro, the code after the preprocess may reach O(2&lt;SUP&gt;n&lt;/SUP&gt;). For example: 
&lt;P&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; F1(x) x,x&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; F2(x) F1(x),F1(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; F3(x) F2(x),F2(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; F4(x) F3(x),F3(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; F5(x) F4(x),F4(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; F6(x) F5(x),F5(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; F7(x) F6(x),F6(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; F8(x) F7(x),F7(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; F9(x) F8(x),F8(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; G1(x) F9(x),F9(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; G2(x) G1(x),G1(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; G3(x) G2(x),G2(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; G4(x) G3(x),G3(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; G5(x) G4(x),G4(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; G6(x) G5(x),G5(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; G7(x) G6(x),G6(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; G8(x) G7(x),G7(x)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; G9(x) G8(x),G8(x) &lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; G9(1);&lt;BR&gt;}&lt;BR&gt;
&lt;P&gt;Of course, different compilers handle this kind of overflow differently. GCC will fail directly (when all of the resource are eaten up), and VC will give ICE (Internal Compiler Error). 
&lt;P&gt;2. Template 
&lt;P&gt;a. Nesting&lt;BR&gt;Similarly, there're nest level limit for template, but we can easily deceive the compiler.&lt;BR&gt;Some version of GCC will enter infinite loop when compiles the following code: 
&lt;P&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;&amp;lt;cstddef&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt; &amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt; T&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; Test {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;const&lt;/SPAN&gt; size_t Value=Test&amp;lt;Test&amp;lt;T&amp;gt; &amp;gt;::Value;&lt;BR&gt;};&lt;BR&gt;
&lt;P&gt;VC is wise enough to stop when the nest level limit is exceeded in the above code. But we can use one of VC's bug (you can also treat it as an extension) to write template which requires O(n&lt;SUP&gt;a&lt;/SUP&gt;) compilation time: 
&lt;P&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;&amp;lt;cstddef&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; INNER(A3,N3,A2,N2) \&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;size_t N3&amp;gt;\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; A3\&lt;BR&gt;{\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {N=A3&amp;lt;N3-1&amp;gt;::N+1};\&lt;BR&gt;};\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&amp;gt;\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; A3&amp;lt;0&amp;gt;\&lt;BR&gt;{\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {N=A2&amp;lt;N2-1&amp;gt;::N};\&lt;BR&gt;}; &lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; OUTER(A2,N2,A1,N1,A3,CONTENT) \&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;size_t N2&amp;gt;\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; A2\&lt;BR&gt;{\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CONTENT\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {N=A3&amp;lt;N2&amp;gt;::N};\&lt;BR&gt;};\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&amp;gt;\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; A2&amp;lt;0&amp;gt;\&lt;BR&gt;{\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {N=A1&amp;lt;N1-1&amp;gt;::N};\&lt;BR&gt;}; &lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; LEVEL2(a,b,c) INNER(A##b,N##b,A##a,N##a)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; LEVEL3(a,b,c) OUTER(A##b,N##b,A##a,N##a,A##c,LEVEL2(a##1,b##1,c##1))&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; LEVEL4(a,b,c) OUTER(A##b,N##b,A##a,N##a,A##c,LEVEL3(a##1,b##1,c##1))&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; LEVEL5(a,b,c) OUTER(A##b,N##b,A##a,N##a,A##c,LEVEL4(a##1,b##1,c##1)) &lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;size_t N1&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; A1&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LEVEL5(1,11,111)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {N=A11&amp;lt;N1&amp;gt;::N};&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt; A1&amp;lt;0&amp;gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {N=0};&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt;&amp;nbsp;main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt;&amp;nbsp;A1&amp;lt;20&amp;gt;::N;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;
&lt;P&gt;The interesting thing is that, the standard doesn't allow this kind of specialization in template class. Is this a bug or extension of VC?&lt;BR&gt;&lt;STRONG&gt;A member or a member template may be nested within many enclosing class templates. In an explicit specialization for such a member, the member declaration shall be preceded by a template&amp;lt;&amp;gt; for each enclosing class template that is explicitly specialized.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Based on similar idea, we can write portable version for both GCC and VC. &lt;/P&gt;
&lt;P&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt;&amp;nbsp;INNER(A3,N3)&amp;nbsp;\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt;&amp;nbsp;N3&amp;gt;\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt;&amp;nbsp;A3\&lt;BR&gt;{\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt;&amp;nbsp;f()&amp;nbsp;{}\&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt;&amp;nbsp;OUTER(A2,N2,A1,CONTENT)&amp;nbsp;\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt;&amp;nbsp;N2&amp;gt;\&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;struct&lt;/SPAN&gt;&amp;nbsp;A2\&lt;BR&gt;{\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CONTENT\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;static&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;void&lt;/SPAN&gt;&amp;nbsp;f()&amp;nbsp;{\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A1&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;char&lt;/SPAN&gt;&amp;gt;::f();\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A1&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;short&lt;/SPAN&gt;&amp;gt;::f();\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A1&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt;&amp;gt;::f();\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A1&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt;&amp;gt;::f();\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A1&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;char&lt;/SPAN&gt;&amp;gt;::f();\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A1&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;short&lt;/SPAN&gt;&amp;gt;::f();\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A1&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt;&amp;gt;::f();\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A1&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;unsigned&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;long&lt;/SPAN&gt;&amp;gt;::f();\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}\&lt;BR&gt;};&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt;&amp;nbsp;LEVEL2(a,b)&amp;nbsp;INNER(A##a,T##a)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt;&amp;nbsp;LEVEL3(a,b)&amp;nbsp;OUTER(A##a,T##a,A##b,LEVEL2(a##1,b##1))&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt;&amp;nbsp;LEVEL4(a,b)&amp;nbsp;OUTER(A##a,T##a,A##b,LEVEL3(a##1,b##1))&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt;&amp;nbsp;LEVEL5(a,b)&amp;nbsp;OUTER(A##a,T##a,A##b,LEVEL4(a##1,b##1))&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt;&amp;nbsp;LEVEL6(a,b)&amp;nbsp;OUTER(A##a,T##a,A##b,LEVEL5(a##1,b##1))&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt;&amp;nbsp;LEVEL7(a,b)&amp;nbsp;OUTER(A##a,T##a,A##b,LEVEL6(a##1,b##1))&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt;&amp;nbsp;LEVEL8(a,b)&amp;nbsp;OUTER(A##a,T##a,A##b,LEVEL7(a##1,b##1))&lt;BR&gt;&lt;BR&gt;LEVEL8(1,11)&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt;&amp;nbsp;main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A1&amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt;&amp;gt;::f();&lt;BR&gt;}&lt;BR&gt;
&lt;P&gt;b. Multiple inheritance&lt;BR&gt;C++ allows multiple inheritance, it can be used to hang the compiler. Try the following "Fibonacci" inheritance: 
&lt;P&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;size_t N&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt; Evil:&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;virtual&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt; Evil&amp;lt;N-1&amp;gt;,&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;virtual&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt; Evil&amp;lt;N-2&amp;gt;&lt;BR&gt;{&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;public&lt;/SPAN&gt;:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;virtual&lt;/SPAN&gt; ~Evil() {}&lt;BR&gt;}; &lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt; Evil&amp;lt;1&amp;gt;&lt;BR&gt;{&lt;BR&gt;};&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt;&amp;lt;&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt; Evil&amp;lt;0&amp;gt;&lt;BR&gt;{&lt;BR&gt;}; &lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Evil&amp;lt;100&amp;gt; evil;&lt;BR&gt;}&lt;BR&gt;
&lt;P&gt;c. OLE (Output limit exceeded)&lt;BR&gt;Normally, the compile time for template is O(n), but in contrast, the amount of error message will be O(n&lt;SUP&gt;2&lt;/SUP&gt;). Taking advantage of this, you can make the error message "Output Limit Exceeded". For example: 
&lt;P&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#define&lt;/SPAN&gt; ClassName A &lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;template&lt;/SPAN&gt; &amp;lt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; N&amp;gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;class&lt;/SPAN&gt; ClassName&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;enum&lt;/SPAN&gt; {Value=ClassName&amp;lt;N-1&amp;gt;::Value};&lt;BR&gt;}; &lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt; n=ClassName&amp;lt;0&amp;gt;::Value;&lt;BR&gt;} 
&lt;P&gt;If I change "ClassName" to a very long name (which is widely supported by modern compilers), the error message will be easily OLE.&lt;BR&gt;PS: The above code will cause ICE in VC8. This is the bug of VC8, and VC9 is happy with the code.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8952632" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/VC/default.aspx">VC</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/Bug/default.aspx">Bug</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/GCC/default.aspx">GCC</category></item><item><title>Debug vs Release</title><link>http://blogs.msdn.com/xiangfan/archive/2008/08/30/debug-vs-release.aspx</link><pubDate>Sat, 30 Aug 2008 15:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8909489</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/8909489.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=8909489</wfw:commentRss><description>&lt;P&gt;Someone may wonder what the difference is between Debug and Release mode, and whether it is possible to mix them. 
&lt;P&gt;Here is one example: &lt;A href="http://forums.msdn.microsoft.com/en-US/vcgeneral/thread/775ce067-b225-4141-8b86-2d7e9b61db97/" mce_href="http://forums.msdn.microsoft.com/en-US/vcgeneral/thread/775ce067-b225-4141-8b86-2d7e9b61db97/"&gt;http://forums.msdn.microsoft.com/en-US/vcgeneral/thread/775ce067-b225-4141-8b86-2d7e9b61db97/&lt;/A&gt; 
&lt;P&gt;syperk said: "As a result, I've switched to compiling my debug builds using the /MD switch. If you do this, you also have to undefine the _DEBUG preprocessor macro. Otherwise you get lots of errors about _CrtDebugReportW() not found. This function is apparently inserted into your code if _DEBUG is defined, but is only defined in the debug CRT. As long as optimization is off it seems to be perfectly possible to debug programs compiled this way, and there are no concerns about CRT incompatibility.". 
&lt;P&gt;But that is not true. There are many problems. In my opion, the most important one is that it is not a good idea to link different modules compiled with different compiler options in C++, especially when conditional compilation is involved. 
&lt;P&gt;In fact, "Debug" &amp;amp; "Release" are only two sets of predefined compiler flags and macros definitions provided by the IDE (_DEBUG and NDEBUG are two representing macros). The compiler doesn't aware of that (but it has some magic behind compile option "MD" and "MDd").&lt;BR&gt;The main problem is that program compiled using "Debug" setting and the release runtime don't share the same compiler flags, and they are highly possible to be incompatible. 
&lt;P&gt;For example, if you change "MDd" -&amp;gt; "MD" in your debug configuration, and compile the following code (don't remove the _DEBUG macro, otherwise the "Debug" version is no longer a debug version (/MDd will define this macro implicitly, and IDE will explicitly define it via compiler flag)) : 
&lt;P&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;&amp;lt;iostream&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#include&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;&amp;lt;string&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;using&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;namespace&lt;/SPAN&gt;&amp;nbsp;std;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;int&lt;/SPAN&gt;&amp;nbsp;main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::string&amp;nbsp;str;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;return&lt;/SPAN&gt;&amp;nbsp;0;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;
&lt;P&gt;You'll find that the program function properly. If you check the generated exe, you'll find that it refer to two dlls, one is msvcp90d.dll, the other is msvcr90.dll. Oops! You're mixing the debug and release runtime libraries! And that hide the potential incompatibility! 
&lt;P&gt;The magic is here (in use_ansi.h): 
&lt;P&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#ifdef&lt;/SPAN&gt;&amp;nbsp;_DEBUG&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#pragma&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;comment&lt;/SPAN&gt;(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;lib&lt;/SPAN&gt;,&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"msvcprtd"&lt;/SPAN&gt;)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#else&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;/*&amp;nbsp;_DEBUG&amp;nbsp;*/&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#pragma&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;comment&lt;/SPAN&gt;(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;lib&lt;/SPAN&gt;,&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"msvcprt"&lt;/SPAN&gt;)&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;#endif&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;/*&amp;nbsp;_DEBUG&amp;nbsp;*/&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(0,128,0)"&gt;&lt;/SPAN&gt;&lt;BR&gt;
&lt;P&gt;If you disable this trick, and link to msvcp90.dll, you'll get unresolved symbol error, that is because the implementation of string class is different in "Debug" and "Release" mode. This is one example of the incompatibility. 
&lt;P&gt;error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;(struct std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;::_Has_debug_it)" (__imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@U_Has_debug_it@01@@Z) referenced in function _main 
&lt;P&gt;It's fortunate that this is a linker error. Otherwise, you'll waste lots of time in debugging to find out the subtle incompatibility. 
&lt;P&gt;STL in VC9 devotes lots of efforts to prevent break like this, then you can disable macros like "_HAS_ITERATOR_DEBUGGING" as you like, and keep your code compatible with the runtime (which is compiled with the macro enabled). But it only applies when you stick to debug or stick to release. It is really tricky to guarantee that, and I think you should never rely on this.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8909489" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/VC/default.aspx">VC</category></item><item><title>Conformance macros in VC STL</title><link>http://blogs.msdn.com/xiangfan/archive/2008/08/30/conformance-macros-in-vc-stl.aspx</link><pubDate>Sat, 30 Aug 2008 11:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8908873</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/8908873.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=8908873</wfw:commentRss><description>&lt;P&gt;In VC STL, there are two macros called "_HAS_IMMUTABLE_SETS" and "_HAS_STRICT_CONFORMANCE" which are defined in yvals.h. They are related to some defects in the C++ standard 2003. 
&lt;P&gt;1. _HAS_IMMUTABLE_SETS will influence the constness of set::iterator. 
&lt;P&gt;Associative containers require its elements to be sorted, so modify them will be dangerous. But the standard doesn't prohibit the programmer to do that. 
&lt;P&gt;In C++0x, the following statement is added for associative containter:&lt;BR&gt;For associative containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators&lt;BR&gt;(In the standard, it is said:&lt;BR&gt;Constant iterators do not satisfy the requirements for output iterators, and the result of the expression *i (for constant iterator i) cannot be used in an expression where an lvalue is required.)&lt;BR&gt;That means you cannot modify the value of the elements using iterator any more. 
&lt;P&gt;Discussion: &lt;A href="http://www.cpptalk.net/image-vp135370.html" mce_href="http://www.cpptalk.net/image-vp135370.html"&gt;http://www.cpptalk.net/image-vp135370.html&lt;/A&gt; 
&lt;P&gt;2. _HAS_STRICT_CONFORMANCE will influence two places: 
&lt;P&gt;a. For set, multiset, map and multimap 
&lt;P&gt;void erase(const_iterator position);&lt;BR&gt;size_type erase(const key_type&amp;amp; x);&lt;BR&gt;void erase(const_iterator first, const_iterator last); 
&lt;P&gt;-&amp;gt; 
&lt;P&gt;iterator erase(const_iterator position);&lt;BR&gt;size_type erase(const key_type&amp;amp; x);&lt;BR&gt;iterator erase(const_iterator first, const_iterator last); 
&lt;P&gt;In C++03, erase in associative containers will not return the iterator, which is incompatible with sequence containers. It is fixed in C++0x&lt;BR&gt;VC's extension provides the return value for erase. _HAS_STRICT_CONFORMANCE will disable this extension. 
&lt;P&gt;Discussion: &lt;A href="http://www.tech-archive.net/Archive/VC/microsoft.public.vc.stl/2005-10/msg00030.html" mce_href="http://www.tech-archive.net/Archive/VC/microsoft.public.vc.stl/2005-10/msg00030.html"&gt;http://www.tech-archive.net/Archive/VC/microsoft.public.vc.stl/2005-10/msg00030.html&lt;/A&gt;&lt;BR&gt;Further Discussion: &lt;A href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#103" mce_href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#103"&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#103&lt;/A&gt; 
&lt;P&gt;b. For codecvt::do_length(stateT&amp;amp; state, const externT* from, const externT* from_end, size_t max) const; 
&lt;P&gt;In C++03, codecvt&amp;lt;wchar_t, char, mbstate_t&amp;gt; and codecvt&amp;lt;char, char, mbstate_t&amp;gt; should return the lesser of max and (from_end-from).&lt;BR&gt;This is weakened in C++0x. Only codecvt&amp;lt;char, char, mbstate_t&amp;gt; is required to behave like that. 
&lt;P&gt;BTW: VC's STL implementation is provided by Dinkumware. You can see "P.J. Plauger" at the end of each STL file. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8908873" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/xiangfan/archive/tags/VC/default.aspx">VC</category></item></channel></rss>