<?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</title><link>http://blogs.msdn.com/xiangfan/default.aspx</link><description>I'm a developer at C++ Shanghai team. I'm interested in everything related to 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>Visual C++ Shanghai Team Blog is Online</title><link>http://blogs.msdn.com/xiangfan/archive/2009/09/11/visual-c-shanghai-team-blog-is-online.aspx</link><pubDate>Fri, 11 Sep 2009 16:57:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9894184</guid><dc:creator>xiangfan</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9894184.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9894184</wfw:commentRss><description>&lt;p&gt;I’m glad that our team blog is now online (&lt;a title="http://blogs.msdn.com/vcshblog/" href="http://blogs.msdn.com/vcshblog/"&gt;http://blogs.msdn.com/vcshblog/&lt;/a&gt;). It is in Chinese and is targeted to Chinese developers.&lt;/p&gt; &lt;p&gt;We will write technical articles related to our work in Shanghai and also translate articles on VCBlog into Chinese.&lt;/p&gt; &lt;p&gt;Here are articles posted by our team on VCBlog:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://blogs.msdn.com/vcblog/archive/2009/05/21/dynamicbase-and-nxcompat.aspx"&gt;/DYNAMICBASE and /NXCOMPAT&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://blogs.msdn.com/vcblog/archive/2009/07/21/linker-warning-lnk4221-and-some-tips-to-avoid-it.aspx"&gt;Linker warning LNK4221, and some tips to avoid it&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://blogs.msdn.com/vcblog/archive/2009/09/10/linker-throughput.aspx"&gt;Linker throughput&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9894184" width="1" height="1"&gt;</description></item><item><title>Output Text in Unicode</title><link>http://blogs.msdn.com/xiangfan/archive/2009/08/04/output-text-in-unicode.aspx</link><pubDate>Tue, 04 Aug 2009 16:35:35 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9857123</guid><dc:creator>xiangfan</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9857123.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9857123</wfw:commentRss><description>&lt;p&gt;According to C standard, it only supports output text in MBCS (Multi-Byte Character String):&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf" target="_blank"&gt;n1124.pdf&lt;/a&gt;, 7.19.3/12&lt;/p&gt; &lt;p&gt;The wide character output functions convert wide characters to multibyte characters and write them to the stream as if they were written by successive calls to the fputwc function. Each conversion occurs as if by a call to the wcrtomb function, with the conversion state described by the stream’s own mbstate_t object. The byte output functions write characters to the stream as if by successive calls to the fputc function.  &lt;p&gt;However, MBCS doesn’t support mixing characters in different code page. For example, you can’t use both Chinese and Japanese.&lt;/p&gt; &lt;p&gt;VC provides extension to allow you to output text in Unicode:&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(0,0,255)"&gt;#include&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(163,21,21)"&gt;&amp;lt;locale.h&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;#include&lt;/span&gt;&amp;nbsp;&lt;span style="color: rgb(163,21,21)"&gt;&amp;lt;io.h&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;fcntl.h&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;void&lt;/span&gt; OutputMBCS(FILE *f)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,128,0)"&gt;// ".936" is the code page for Simplified Chinese&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,128,0)"&gt;// However, you can't use ".1200" (code page for Unicode) to output text in Unicode&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; setlocale(LC_CTYPE, &lt;span style="color: rgb(163,21,21)"&gt;".936"&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,128,0)"&gt;// My name in Chinese: "范翔"&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fwprintf(f, L&lt;span style="color: rgb(163,21,21)"&gt;"%s"&lt;/span&gt;, L&lt;span style="color: rgb(163,21,21)"&gt;"\x8303\x7FD4"&lt;/span&gt;);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,128,0)"&gt;// The text in the file is encoded in GBK&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; OutputUnicode(FILE *f)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _setmode(_fileno(f), _O_U16TEXT);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fwprintf(f, L&lt;span style="color: rgb(163,21,21)"&gt;"%s"&lt;/span&gt;, L&lt;span style="color: rgb(163,21,21)"&gt;"\x8303\x7FD4"&lt;/span&gt;);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0,128,0)"&gt;// The text in the file is encoded in Unicode&lt;/span&gt;&lt;br&gt;}&lt;/p&gt; &lt;p&gt;For more information, please check the following post: &lt;a href="http://blogs.msdn.com/michkap/archive/2008/03/18/8306597.aspx"&gt;http://blogs.msdn.com/michkap/archive/2008/03/18/8306597.aspx&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9857123" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/xiangfan/archive/tags/VC/default.aspx">VC</category></item><item><title>IDA Pro 5.5 is released</title><link>http://blogs.msdn.com/xiangfan/archive/2009/06/17/ida-pro-5-5-is-released.aspx</link><pubDate>Wed, 17 Jun 2009 13:32:10 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9769014</guid><dc:creator>xiangfan</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9769014.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9769014</wfw:commentRss><description>&lt;p&gt;IDA Pro 5.5 ships 12th of June 2009.&lt;/p&gt; &lt;p&gt;The change list is here:&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.hex-rays.com/idapro/55/index.htm" href="http://www.hex-rays.com/idapro/55/index.htm"&gt;http://www.hex-rays.com/idapro/55/index.htm&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9769014" width="1" height="1"&gt;</description></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>Enable syntax highlighting for TR1 headers in VS2008 SP1</title><link>http://blogs.msdn.com/xiangfan/archive/2008/12/13/enable-syntax-highlighting-for-tr1-headers-in-vs2008-sp1.aspx</link><pubDate>Sat, 13 Dec 2008 06:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9205673</guid><dc:creator>xiangfan</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/xiangfan/comments/9205673.aspx</comments><wfw:commentRss>http://blogs.msdn.com/xiangfan/commentrss.aspx?PostID=9205673</wfw:commentRss><description>&lt;P&gt;Unfortunately, VS2008 SP1 doesn't recognize C++ tr1 headers. That means there are no syntax highlighting and no intellisense for these files.&lt;/P&gt;
&lt;P&gt;This is a bug, but you can fix it by yourself. The trick is in the registry. VS maintains a list of extensionless files, and will treat them as cpp files.&lt;/P&gt;
&lt;P&gt;It is under: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Languages\Extensionless Files\{B2F072B0-ABC1-11D0-9D62-00C04FD9DFD9}&lt;/P&gt;
&lt;P&gt;Just add tr1 headers into it and you'll now get full support of new tr1 features. Here is the reg file:&lt;/P&gt;
&lt;P&gt;Windows Registry Editor Version 5.00 
&lt;P&gt;[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Languages\Extensionless Files\{B2F072B0-ABC1-11D0-9D62-00C04FD9DFD9}]&lt;BR&gt;"array"=""&lt;BR&gt;"random"=""&lt;BR&gt;"regex"=""&lt;BR&gt;"tuple"=""&lt;BR&gt;"type_traits"=""&lt;BR&gt;"unordered_map"=""&lt;BR&gt;"unordered_set"=""&lt;BR&gt;"xawrap"=""&lt;BR&gt;"xawrap0"=""&lt;BR&gt;"xawrap1"=""&lt;BR&gt;"xawrap2"=""&lt;BR&gt;"xfwrap"=""&lt;BR&gt;"xfwrap1"=""&lt;BR&gt;"xrefwrap"=""&lt;BR&gt;"xtr1common"=""&lt;BR&gt;"xxbind0"=""&lt;BR&gt;"xxbind1"=""&lt;BR&gt;"xxcallfun"=""&lt;BR&gt;"xxcallobj"=""&lt;BR&gt;"xxcallpmf"=""&lt;BR&gt;"xxcallwrap"=""&lt;BR&gt;"xxfunction"=""&lt;BR&gt;'xxmem_fn"=""&lt;BR&gt;"xxpmfcaller"=""&lt;BR&gt;"xxrefwrap"=""&lt;BR&gt;"xxresult"=""&lt;BR&gt;"xxtuple0"=""&lt;BR&gt;"xxtuple1"=""&lt;BR&gt;"xxtype_traits"=""&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9205673" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/xiangfan/attachment/9205673.ashx" length="1222" type="application/octet-stream" /><category domain="http://blogs.msdn.com/xiangfan/archive/tags/VC/default.aspx">VC</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></channel></rss>