﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-魔のkyo的工作室-随笔分类-C++</title><link>http://cnitblog.com/luckydmz/category/8972.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 10 Jan 2020 18:05:58 GMT</lastBuildDate><pubDate>Fri, 10 Jan 2020 18:05:58 GMT</pubDate><ttl>60</ttl><item><title>C++ std::chrono中时钟的用法以及和time_t的转换和格式化</title><link>http://www.cnitblog.com/luckydmz/archive/2020/01/07/92011.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 07 Jan 2020 04:20:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/01/07/92011.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92011.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/01/07/92011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92011.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92011.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br />#include&nbsp;&lt;chrono&gt;<br />#include&nbsp;&lt;sstream&gt;<br />#include&nbsp;&lt;iomanip&gt;<br /><br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br /><br />constexpr&nbsp;int64_t&nbsp;SEC&nbsp;=&nbsp;1000000;<br />constexpr&nbsp;int64_t&nbsp;MIN&nbsp;=&nbsp;SEC&nbsp;*&nbsp;60;<br />constexpr&nbsp;int64_t&nbsp;HOUR&nbsp;=&nbsp;MIN&nbsp;*&nbsp;60;<br />constexpr&nbsp;int64_t&nbsp;DAY&nbsp;=&nbsp;HOUR&nbsp;*&nbsp;24;<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;返回当前时间作为&nbsp;格林威治(GMT)时间&nbsp;距离&nbsp;GMT时间&nbsp;1970-1-1&nbsp;00:00:00&nbsp;的微秒数</span><span style="color: #008000; "><br /></span>int64_t&nbsp;get_time_us()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;chrono::system_clock&nbsp;clock;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;chrono::duration_cast&lt;chrono::microseconds&gt;(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clock.now().time_since_epoch()).count();<br />}<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;返回当前时间作为&nbsp;本地（北京）时间&nbsp;距离&nbsp;GMT时间&nbsp;1970-1-1&nbsp;00:00:00&nbsp;的微秒数，等于get_gmtime_us加8小时</span><span style="color: #008000; "><br /></span>int64_t&nbsp;get_localtime_us()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;get_time_us()&nbsp;+&nbsp;HOUR&nbsp;*&nbsp;8;<br />}<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;格林威治时间的微秒数格式化成本地时间字符串</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">string</span>&nbsp;gmtime2localstr(int64_t&nbsp;time_us,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">string</span>&amp;&nbsp;fmt="%Y-%m-%d&nbsp;%H:%M:%S")<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;stringstream&nbsp;ss;<br />&nbsp;&nbsp;&nbsp;&nbsp;time_t&nbsp;t&nbsp;=&nbsp;time_us&nbsp;/&nbsp;SEC;<br />&nbsp;&nbsp;&nbsp;&nbsp;auto&nbsp;tm&nbsp;=&nbsp;std::localtime(&amp;t);<br />&nbsp;&nbsp;&nbsp;&nbsp;ss&nbsp;&lt;&lt;&nbsp;std::put_time(tm,&nbsp;fmt.c_str());<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;ss.str();<br />}<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;本地时间字符串解析成格林威治时间的微秒数</span><span style="color: #008000; "><br /></span>int64_t&nbsp;localstr2gmtime(<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&amp;&nbsp;s,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&amp;&nbsp;fmt="%Y-%m-%d&nbsp;%H:%M:%S")<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;stringstream&nbsp;ss;<br />&nbsp;&nbsp;&nbsp;&nbsp;ss&nbsp;&lt;&lt;&nbsp;s;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;tm&nbsp;tm;<br />&nbsp;&nbsp;&nbsp;&nbsp;ss&nbsp;&gt;&gt;&nbsp;std::get_time(&amp;tm,&nbsp;fmt.c_str());<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(int64_t)mktime(&amp;tm)&nbsp;*&nbsp;SEC;<br />}<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;字符串转微秒数，不考虑时区</span><span style="color: #008000; "><br /></span>std::<span style="color: #0000FF; ">string</span>&nbsp;time2str(int64_t&nbsp;time_us,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&amp;&nbsp;fmt="%Y-%m-%d&nbsp;%H:%M:%S")<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;stringstream&nbsp;ss;<br />&nbsp;&nbsp;&nbsp;&nbsp;time_t&nbsp;t&nbsp;=&nbsp;time_us&nbsp;/&nbsp;SEC;<br />&nbsp;&nbsp;&nbsp;&nbsp;auto&nbsp;tm&nbsp;=&nbsp;std::gmtime(&amp;t);<br />&nbsp;&nbsp;&nbsp;&nbsp;ss&nbsp;&lt;&lt;&nbsp;std::put_time(tm,&nbsp;fmt.c_str());<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;ss.str();<br />}<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;微秒数转字符串，不考虑时区</span><span style="color: #008000; "><br /></span>int64_t&nbsp;str2time(<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&amp;&nbsp;s,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;std::<span style="color: #0000FF; ">string</span>&amp;&nbsp;fmt="%Y-%m-%d&nbsp;%H:%M:%S")<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;stringstream&nbsp;ss;<br />&nbsp;&nbsp;&nbsp;&nbsp;ss&nbsp;&lt;&lt;&nbsp;s;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;tm&nbsp;tm;<br />&nbsp;&nbsp;&nbsp;&nbsp;ss&nbsp;&gt;&gt;&nbsp;std::get_time(&amp;tm,&nbsp;fmt.c_str());<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(int64_t)mktime(&amp;tm)&nbsp;*&nbsp;SEC&nbsp;+&nbsp;HOUR&nbsp;*&nbsp;8;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;这里&nbsp;+&nbsp;8&nbsp;HOURs是因为mktime内部考虑了时区，我期望有一个gmmktime函数，但是标准库似乎并没有</span><span style="color: #008000; "><br /></span>}</div>其实对于time_t或者说从格林尼治1970年1月1日0时的毫秒数来说，并不需要区分时区，全球都是同一个毫秒数只是在对应到有时间表示时才需要区分时区，<br />这里之所有引入<span style="background-color: #ffffff;">get_localtime_us是为了方便时间计算，例如计算当前时间的下一个8点40的微秒数，如果任意天00:00对齐到 % DAY == 0这样会比较好算。<br /></span><div>auto _08_40 = (HOUR * 8 + MIN * 40);</div><div>auto next_08_40 = ((time_us - _08_40) / DAY + 1) * DAY + _08_40;</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-01-07 12:20 <a href="http://www.cnitblog.com/luckydmz/archive/2020/01/07/92011.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用iconv在Linux上进行字符编码转换</title><link>http://www.cnitblog.com/luckydmz/archive/2019/11/27/91964.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Wed, 27 Nov 2019 10:36:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2019/11/27/91964.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/91964.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2019/11/27/91964.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/91964.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/91964.html</trackback:ping><description><![CDATA[<div>
Windows上参考<br />
http://www.cnitblog.com/luckydmz/archive/2010/03/03/64458.html
</div>
<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><br />
#include&nbsp;&lt;iconv.h&gt;<br />
#include&nbsp;&lt;cstring&gt;<br />
#include&nbsp;&lt;<span style="color: #0000FF; ">string</span>&gt;<br />
#include&nbsp;&lt;iostream&gt;<br />
<br />
<span style="color: #0000FF; ">class</span>&nbsp;EncodingConvertor<br />
{<br />
<span style="color: #0000FF; ">public</span>:<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;"UTF-8",&nbsp;"GBK"</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;EncodingConvertor(<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;toEncoding,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;fromEncoding)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_iconv&nbsp;=&nbsp;iconv_open(toEncoding,&nbsp;fromEncoding);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;std::<span style="color: #0000FF; ">string</span>&nbsp;convert(<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;<span style="color: #0000FF; ">in</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;constexpr&nbsp;size_t&nbsp;BLOCK_SIZE&nbsp;=&nbsp;1024;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;iconv可以分块转换，对于特别长的字符串（特别大的文件）</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;inlen&nbsp;=&nbsp;strlen(<span style="color: #0000FF; ">in</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;outbuflen&nbsp;=&nbsp;std::max(inlen&nbsp;*&nbsp;2,&nbsp;BLOCK_SIZE);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;pin&nbsp;=&nbsp;<span style="color: #0000FF; ">in</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;outbuf&nbsp;=&nbsp;(<span style="color: #0000FF; ">char</span>*)malloc(outbuflen);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;pout&nbsp;=&nbsp;outbuf;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;ret&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;perlen&nbsp;=&nbsp;BLOCK_SIZE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(pout&nbsp;+&nbsp;perlen&nbsp;&gt;&nbsp;outbuf&nbsp;+&nbsp;outbuflen - 1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;如果outbuf后面剩余空间不足一个转换块大小，就重新分配空间</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;pout_offset&nbsp;=&nbsp;pout&nbsp;-&nbsp;outbuf;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outbuflen&nbsp;=&nbsp;std::max(outbuflen&nbsp;*&nbsp;2,&nbsp;BLOCK_SIZE);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outbuf&nbsp;=&nbsp;(<span style="color: #0000FF; ">char</span>*)realloc(outbuf,&nbsp;outbuflen);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pout&nbsp;=&nbsp;outbuf&nbsp;+&nbsp;pout_offset;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;outbuf可能指向新地址，所以要把pout偏移过去</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;iconv(_iconv,&nbsp;(<span style="color: #0000FF; ">char</span>**)&amp;pin,&nbsp;&amp;inlen,&nbsp;&amp;pout,&nbsp;&amp;perlen);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(perlen&nbsp;==&nbsp;BLOCK_SIZE)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;转移前后perlen没有变化应该是出错了</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outbuf[0]&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">break</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>(ret&nbsp;==&nbsp;-1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *pout = 0;</div><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::<span style="color: #0000FF; ">string</span>&nbsp;r(outbuf);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(outbuf);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;r;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;~EncodingConvertor()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iconv_close(_iconv);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<span style="color: #0000FF; ">private</span>:<br />
&nbsp;&nbsp;&nbsp;&nbsp;iconv_t&nbsp;_iconv;<br />
};<br />
<br />
<span style="color: #0000FF; ">int</span>&nbsp;main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;EncodingConvertor&nbsp;convertor("UTF-8",&nbsp;"GBK");<br />
&nbsp;&nbsp;&nbsp;&nbsp;std::<span style="color: #0000FF; ">string</span>&nbsp;s&nbsp;=&nbsp;convertor.convert("GBK&nbsp;string");<br />
&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;s&nbsp;&lt;&lt;&nbsp;std::endl;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br />
}<br />
<br />
</div>
<div><br />
</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/91964.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2019-11-27 18:36 <a href="http://www.cnitblog.com/luckydmz/archive/2019/11/27/91964.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python使用msgpack对任意单层POD类型class编解码</title><link>http://www.cnitblog.com/luckydmz/archive/2019/11/20/91959.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 19 Nov 2019 16:00:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2019/11/20/91959.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/91959.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2019/11/20/91959.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/91959.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/91959.html</trackback:ping><description><![CDATA[<div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;msgpack<br /><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;obj_dict_serializer(obj):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;msgpack.dumps(vars(obj))<br /><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;obj_dict_deserializer(T):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;deserializer(buf):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;T()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dic&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;msgpack.unpackb(buf)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;k,v&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">&nbsp;dic.items():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;k.decode()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;type(v)</span><span style="color: #000000; ">==</span><span style="color: #000000; ">bytes:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;v.decode()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setattr(obj,&nbsp;k,&nbsp;v)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;obj<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;deserializer<br /><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;obj_list_serializer(obj):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;msgpack.dumps(list(vars(obj).values()))<br /><br /></span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;obj_list_deserializer(T):<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">def</span><span style="color: #000000; ">&nbsp;deserializer(buf):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;T()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;k,&nbsp;v&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">&nbsp;zip(vars(obj).keys(),&nbsp;msgpack.unpackb(buf)):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;type(v)</span><span style="color: #000000; ">==</span><span style="color: #000000; ">bytes:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;v.decode()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setattr(obj,&nbsp;k,&nbsp;v)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;obj<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;deserializer<br /><br /><br /></span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800080; ">__name__</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">'</span><span style="color: #800000; ">__main__</span><span style="color: #800000; ">'</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">from</span><span style="color: #000000; ">&nbsp;dataclasses&nbsp;</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;dataclass<br />&nbsp;&nbsp;&nbsp;&nbsp;@dataclass<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Stu:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id&nbsp;:&nbsp;int&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name:&nbsp;str&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">""</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stuno:&nbsp;str&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">""</span><span style="color: #000000; "><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;stu1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Stu(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">张三</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">190003160</span><span style="color: #800000; ">"</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;stu2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Stu(</span><span style="color: #000000; ">2</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">李四</span><span style="color: #800000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">190003161</span><span style="color: #800000; ">"</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;buf1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;obj_dict_serializer(stu1)<br />&nbsp;&nbsp;&nbsp;&nbsp;stu1_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;obj_dict_deserializer(Stu)(buf1)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(stu1,&nbsp;stu1_)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(stu1&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;stu1_)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;buf2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;obj_dict_serializer(stu2)<br />&nbsp;&nbsp;&nbsp;&nbsp;stu2_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;obj_dict_deserializer(Stu)(buf2)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(stu2,&nbsp;stu2_)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">(stu2&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;stu2_)<br /><br /><br /></span></div></div><div>配合在C++上使用msgpack.hpp 像class、struct中添加 MSGPACK_DEFINE 或 MSGPACK_DEFINE_MAP，可以实现python和C++之间的数据互传后的编解码</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/91959.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2019-11-20 00:00 <a href="http://www.cnitblog.com/luckydmz/archive/2019/11/20/91959.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>可变模版参数(variadic templates)</title><link>http://www.cnitblog.com/luckydmz/archive/2019/11/09/91946.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Sat, 09 Nov 2019 05:23:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2019/11/09/91946.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/91946.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2019/11/09/91946.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/91946.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/91946.html</trackback:ping><description><![CDATA[<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">C++11引入了一个很强大的模板功能，即可变模板参数(variadic templates)，</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">它允许定义出<span style="color: #df402a;">可变参数个数</span>，同时<span style="color: #df402a;">可变参数类型</span>的模板，看一个简单的例子</div><div id="3967-1573271315506" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">cstdio</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">template&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;通过typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />声明的Args称为模板参数包，注意<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />是写在typename后面的</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #008000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;func(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Args</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; "><img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;args)&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;这里的const&nbsp;Args&amp;<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />称为函数参数类型包，而声明出的args称为函数参数包</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;printf(args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />);&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;这里的args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />称为对函数参数包的展开</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">}<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;func(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;%d</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Hello&nbsp;world</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">123</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">15</span> <span style="color: #000000; "><br /></span></div>
</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">输出为</div><div><div style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left: 3px solid #e8e8e8; margin: 0px 5px;">Hello world 123</div></div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">上面的展示很简单明确，现在我们基本知道可变模板参数是个什么东西了。那么它有什么用呢，下面我们来做一些稍微复杂一点的事，如果我们不用printf这样的接受可变长参数列表的函数作为输出，而使用cout该怎么修改上面的代码呢？下面我们稍作修改，<span style="font-weight: bold;">通过递归调用把参数一个一个拆出来</span>。</div><div id="9320-1573271876443" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">cstdio</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;递归终止</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #008000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;func()<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">template&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename&nbsp;T,&nbsp;typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;func(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;T</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;obj,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Args</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; "><img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;args)<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;obj&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;func(args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />);&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;递归调用</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">}<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;func(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Hello&nbsp;world</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">123</span><span style="color: #000000; ">);&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">因为改成通过cin，前面的格式化字符串删掉了</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">}</span></div>

</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">通过增加在模板参数包前面增加一个参数T接受一个参数，再把后面的所有参数递归调用，就实现了一个一个拆出来，最后的调用中args...是可以为0个参数的，这时候调用到了上面的重载函数func()什么都不做。我们可能会想，能不能不写一个空的func()直接在模板函数里面判断args携带的参数个数来终止递归呢，答案是：可以的，但没那么简单。取得可变模板参数的个数可以使用sizeof...()或tuple_size&lt;&gt;::value，下面实现一下</div><div id="5693-1573272773533" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">cstdio</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">template&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename&nbsp;T,&nbsp;typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;func(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;T</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;obj,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Args</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; "><img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;args)<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;obj&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">sizeof</span><span style="color: #000000; "><img src="http://www.cnitblog.com/Images/dot.gif" alt="" />(Args)&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;{<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func(args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />);&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;递归调用</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;func(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Hello&nbsp;world</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">123</span><span style="color: #000000; ">);&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">因为改成通过cin，前面的格式化字符串删掉了</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">}<br /></span><span style="color: #008080; ">18</span> <span style="color: #000000; "><br /></span></div>
</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">上面的代码试图通过判断sizeof...(Args)是否大于0决定是否继续递归，但是上面的代码会编译错误，因为if的判断是在运行期才做的，对func(args...)的调用在编译时就要有匹配的函数存在，而当args一个参数都没有时，编译器找不到匹配的函数进行调用（func至少接受一个参数T）。</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">所以问题的关键点是if分支是运行期的分支，如果我们做一个编译期的分支不就可以解决了么。</div><div id="6854-1573273964503" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">cstdio</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">template&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename&nbsp;T,&nbsp;typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;func(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;T</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;obj,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Args</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; "><img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;args);<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;声明一个带有一个bool参数的模板struct</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;Flag</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;If_Func;<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;下面对bool参数分别进行true/false两种特化实现，以此实现编译期的分支</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">template</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;If_Func</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;call&nbsp;(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Args</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; "><img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;args)&nbsp;{<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func(args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />);<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; ">template</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;If_Func</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;call(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Args</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; "><img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;args)&nbsp;{<br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; ">template&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename&nbsp;T,&nbsp;typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;func(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;T</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;obj,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Args</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; "><img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;args)<br /></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;obj&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">35</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;constexpr&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;flag&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">sizeof</span><span style="color: #000000; "><img src="http://www.cnitblog.com/Images/dot.gif" alt="" />(Args)&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">36</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;If_Func</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">flag</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::call(args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />);<br /></span><span style="color: #008080; ">37</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">38</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">39</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">40</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">41</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;func(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Hello&nbsp;world</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">123</span><span style="color: #000000; ">);&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">因为改成通过cin，前面的格式化字符串删掉了</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">42</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">}</span></div>

</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">上面引入了一个If_Func，这个东西从语法层面来说就是类模板和模板特化，不是新东西，但是这种用法一般被称为<span style="color: #df402a;">模板元编程</span>，C++1x里有一个头文件&lt;<span style="color: #df402a;">type_traits</span>&gt;里面提供了很多模板可以帮助我们进行各种判断，比如判断一个类型是否指针，是否POD，一个类是否是另一个类的子类，等等，可以辅助我们进行模板元编程，有兴趣的自行搜索了解。</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">下面我们讲另一个东西，元组(tuple)，它可以看成是对std::pair的n个元素扩充</div><div id="9866-1573275255880" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">tuple</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /><br /></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;tuple</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;t&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;make_tuple(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">3.14</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Hello&nbsp;world</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;typeid(t).name()&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;std::tuple_size</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">decltype(t)</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::value&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;输出tuple的元素个数</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;std::</span><span style="color: #0000FF; ">get</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(t)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;输出tuple的第0个元素</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;std::</span><span style="color: #0000FF; ">get</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(t)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;输出tuple的第1个元素</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;std::</span><span style="color: #0000FF; ">get</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(t)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;输出tuple的第2个元素</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">}</span></div>
</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">这里不展开讲tuple的用法，我们注意，tuple的模板参数其实类型和数量都是可变的，事实上它就是利用了可变模板参数来实现的。怎么实现呢，大概是这样</div><div id="7712-1573276079036" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;my_tuple;<br /><br />template</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;my_tuple</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; "><br />{<br /><br />};<br /><br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename&nbsp;T,&nbsp;typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;my_tuple</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T,&nbsp;Args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" /></span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;:&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;my_tuple</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" /></span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />{<br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /><br /></span><span style="color: #0000FF; ">protected</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;_obj;<br />};</span></div>
</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">通过递归继承的方式，每次把一个参数拆出来作为成员变量，其余的参数丢给基类，直到参数为空。</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">标准库并没有实现tuple的输出，现在产生一个问题，我们自己能否实现一个tuple的输出函数呢。</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">要实现的就是如果我们使用</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">cout &lt;&lt; make_tuple(123, 3.14, "Hello") &lt;&lt; endl;</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">可以像python里面</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">print( (123, 3.14, "Hello") )</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">输出元组一样，打印出类似 (123, 3.14, 'Hello')</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">我们要实现的函数原型是这样</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">template &lt;typename... Args&gt;</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">ostream&amp; operator &lt;&lt; (ostream&amp; out, const tuple&lt;Args...&gt; t);</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">直接给出代码，里面再次用到了所谓的模板元编程技巧。</div><div id="4187-1573276630545" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">tuple</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">sstream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /><br />template&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">size_t&nbsp;N</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;PrintHelper;<br /><br />template&nbsp;</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;PrintHelper</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;recursive_print(ostream</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;tuple</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" /></span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;t)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;std::</span><span style="color: #0000FF; ">get</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(t)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br />template&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">size_t&nbsp;N</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;PrintHelper<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;recursive_print(ostream</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;tuple</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" /></span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;t)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrintHelper</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">N&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::recursive_print(</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">,&nbsp;t);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;std::</span><span style="color: #0000FF; ">get</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">N&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(t)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;print(ostream</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;tuple</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" /></span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;t)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrintHelper</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">N&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::recursive_print(</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">,&nbsp;t);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;std::</span><span style="color: #0000FF; ">get</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">N&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(t)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">)</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br /><br />template&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />&nbsp;Args</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />ostream</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;(ostream</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;tuple</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Args<img src="http://www.cnitblog.com/Images/dot.gif" alt="" /></span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;t)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;PrintHelper</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">tuple_size</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">decltype(t)</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::value&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::print(</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">,&nbsp;t);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;PrintHelper&lt;sizeof<img src="http://www.cnitblog.com/Images/dot.gif" alt="" />(Args)&gt;::print(out,&nbsp;t);&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;和上面等价</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">out</span><span style="color: #000000; ">;<br />}<br /><br /></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;std::make_tuple(</span><span style="color: #000000; ">123</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">3.14</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Hello</span><span style="color: #000000; ">"</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />}</span></div>

</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">事实上这里会输出</div><div><div style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left: 3px solid #e8e8e8; margin: 0px 5px;">(123, 3.14, Hello)</div></div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">Hello的两端并没有引号，如果想加上引号，可以再次利用模板元编程技巧通过编译时的分支把string类型的输出方法特化，此处不再给出具体代码，留给读者自行探索。</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/91946.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2019-11-09 13:23 <a href="http://www.cnitblog.com/luckydmz/archive/2019/11/09/91946.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Boost和C++1x最值得学习的库概览</title><link>http://www.cnitblog.com/luckydmz/archive/2019/11/08/91945.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Fri, 08 Nov 2019 10:05:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2019/11/08/91945.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/91945.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2019/11/08/91945.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/91945.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/91945.html</trackback:ping><description><![CDATA[<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">Boost库分两种</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">header-only的 和 header + lib的</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">大多数都是header-only的，直接包含头文件就可以用。header + lib由一组头文件和一个库文件构成，可以自己用下载下来的代码编译出库文件或者直接在网上下载对应版本编译好的库。</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">需要连接lib的有以下库：</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    <span style="color: #bfbfbf;">Boost.Chrono	已经标准化 </span><span style="color: #df402a;">std::chrono</span><span style="color: #bfbfbf;"> C++11</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    <span style="color: #df402a;">Boost.Context	C++的协程支持（Coroutine）</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    <span style="color: #bfbfbf;">Boost.Filesystem	已经标准化 </span><span style="color: #df402a;">std::filesystem</span><span style="color: #bfbfbf;"> C++17 处理文件和路径的</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    Boost.GraphParallel	是Boost.Graph库的扩展，为了支持并行和分布式计算，包含一些图算法</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    Boost.IOStreams	IO流，我觉得最大的特点是可以通过filter进行zlib, gzip 和 bzip2的压缩和解压</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    Boost.Locale	本地化库，最主要是解决字符编码转换的问题，还有些日期货币格式转换</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    Boost.Log		日志库</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    Boost.MPI		用于分布式计算中的消息传递</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    <span style="color: #df402a;">Boost.ProgramOptions	读取 命令行参数 或 配置文件</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    Boost.Python	和pyhon的交互框架</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    <span style="color: #bfbfbf;">Boost.Regex	已经标准化</span><span style="color: #df402a;">std::regex</span><span style="color: #bfbfbf;"> C++11</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    Boost.Serialization	序列化</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    Boost.Signals	信号槽模式的一个实现</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    <span style="color: #bfbfbf;">Boost.Thread	已经标准化</span><span style="color: #df402a;">std::thread</span><span style="color: #bfbfbf;"> C++11</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">   <span style="color: #bfbfbf;"> Boost.Timer		计时器，可以用std::chrono::high_resolution_clock自己实现，所以没必要</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">    Boost.Wave		C++预处理器，似乎是为了方便编写一些对C++代码进行预处理的代码</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">以上被标记为红色的我觉得比较有用，可以学习一下，此外包括header-only的一些库，很多都已经被标准化，这些被标准化的往往是比较有用的，我找了了一下大概有下面这些：</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">&lt;functional&gt; std::bind / std::function / std::ref / std::cref</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">&lt;type_traits&gt; std::is_pod / std::is_base_of / std::enable_if / std::result_of / auto / decltype</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">数组封装 std::array 和vector比固定大小，和原生[]数组比不会退化为指针，有迭代器</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">任意类型 std::any</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">可选类型 std::optional / std::nullopt</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">正则表达式 std::regex</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">编译时分数 std::ratio</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">指针增强 std::shared_ptr  / std::weak_ptr / std::unique_ptr</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">n元组 std::tuple / std::make_tuple / std::get</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">多线程和锁 std::thread / std::mutex / std::lock_guard / std::unique_lock / std::atomic</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">时钟 std::chrono::high_resolution_clock / std::chrono::system_clock / std::chrono::steady</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">HASH表 std::unordered_map / std::unordered_set / std::hash</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">静态断言 static_assert</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">我把相关联的东西合并在了一行，这些可以说是C++1x新标准最值得学习的内容。</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/91945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2019-11-08 18:05 <a href="http://www.cnitblog.com/luckydmz/archive/2019/11/08/91945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过_CRTDBG_MAP_ALLOC宏在VC上启用内存泄漏检测</title><link>http://www.cnitblog.com/luckydmz/archive/2019/11/05/91938.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Mon, 04 Nov 2019 16:34:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2019/11/05/91938.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/91938.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2019/11/05/91938.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/91938.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/91938.html</trackback:ping><description><![CDATA[<div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div id="9230-1572884437045" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /><br /></span><span style="color: #0000FF; ">#define</span><span style="color: #000000; ">&nbsp;_CRTDBG_MAP_ALLOC</span><span style="color: #000000; "><br />#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">crtdbg.h</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /><br /></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;按理说通过定义上面的宏再引入头文件，new就会被重新定义成记录文件和行号的<br /></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;但是实际测试下来没有，不知道为什么，而手动定义是起作用的，Microsoft&nbsp;Visual&nbsp;C++&nbsp;2019&nbsp;16.3.2</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">#define</span><span style="color: #000000; ">&nbsp;new&nbsp;new(_NORMAL_BLOCK,&nbsp;__FILE__,&nbsp;__LINE__)</span><span style="color: #000000; "><br /><br /></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;还有其他选项，可以跳转到定义处查看<br />#define&nbsp;_CRTDBG_ALLOC_MEM_DF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0x01&nbsp;&nbsp;//&nbsp;Turn&nbsp;on&nbsp;debug&nbsp;allocation<br />#define&nbsp;_CRTDBG_LEAK_CHECK_DF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0x20&nbsp;&nbsp;//&nbsp;Leak&nbsp;check&nbsp;at&nbsp;program&nbsp;exit<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;当没有定义_DEBUG宏时，下面的调用会被替换成一个哑的宏，什么都不做</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF&nbsp;</span><span style="color: #000000; ">|</span><span style="color: #000000; ">&nbsp;_CRTDBG_LEAK_CHECK_DF);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;p&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">();<br />}</span></div>
</div><div style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">程序结束有会在输出栏输出如下信息，可以直接双击就会跳转到产生泄漏的文件和行号</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">Detected memory leaks!</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">Dumping objects -&gt;</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">D:\development\cpp_test\Project1\main.cpp(21) : {82} normal block at 0x00000218B2905FC0, 4 bytes long.</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">Data : &lt; &gt; 00 00 00 00</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">Object dump complete.</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/91938.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2019-11-05 00:34 <a href="http://www.cnitblog.com/luckydmz/archive/2019/11/05/91938.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>