﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-I smell magic in the air-随笔分类-模板</title><link>http://www.cppblog.com/izualzhy/category/18368.html</link><description>坚持 相信自己</description><language>zh-cn</language><lastBuildDate>Tue, 13 Dec 2011 14:16:40 GMT</lastBuildDate><pubDate>Tue, 13 Dec 2011 14:16:40 GMT</pubDate><ttl>60</ttl><item><title>error: wrong number of template arguments</title><link>http://www.cppblog.com/izualzhy/archive/2011/12/13/162055.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Tue, 13 Dec 2011 13:41:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/12/13/162055.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/162055.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/12/13/162055.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/162055.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/162055.html</trackback:ping><description><![CDATA[<p>碰到一个error：wrong number of template arguments的错误，不过我写的参数个数是没有问题的。百思不得其解，上网搜了下，看到这里的一个例子： <p><a href="http://stackoverflow.com/questions/851584/default-template-class-argument-confuses-g">http://stackoverflow.com/questions/851584/default-template-class-argument-confuses-g</a> <p>跟我遇到的问题一样，翻译了一小部分，作为笔记，如果哪个地方理解错误请一定指出。英语好的可以直接略过这篇文章了。 <p>不得不感叹模板编程遇到的问题真难理解。 <p>先写个例子程序：</p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">template</span>&lt;<span style="color: #0000ff">typename</span> A,<span style="color: #0000ff">typename</span> B&gt;<br><br><span style="color: #0000ff">class</span> Foo {};<br><br><span style="color: #0000ff">struct</span> Bar {<br><br><span style="color: #0000ff">void</span> method( Foo&lt;<span style="color: #0000ff">int</span>,<span style="color: #0000ff">int</span>&gt; <span style="color: #0000ff">const</span> &amp;stuff = Foo&lt;<span style="color: #0000ff">int</span>,<span style="color: #0000ff">int</span>&gt;());<br><br>};<br><br><span style="color: #0000ff">int</span> main()<br><br>{<br><br><span style="color: #0000ff">return</span> 0;<br><br>}<br></pre><br></div>
<p>如果Foo是单模板的话，没有问题的。
<p>编译了下，看下输出：
<p>$ g++-4.3 test.cpp
<p>test.cpp:5: error: expected ‘,’ or ‘...’ before ‘&gt;’ token
<p>test.cpp:5: error: wrong number of template arguments (1, should be 2)
<p>test.cpp:2: error: provided for ‘template&lt;class A, class B&gt; class Foo’
<p>test.cpp:5: error: default argument missing for parameter 2 of ‘void Bar::method(const Foo&lt;int, int&gt;&amp;, int)’
<p>$ g++-4.4 test.cpp
<p>$
<p>可以看到g++4.3编译错误，g++4.4却编译的过。
<p>接下来为了阐述这个问题，我统一使用g++4.3来编译。
<p>编译器认为我想要写这么一个函数：</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">void</span> Bar::method(<span style="color: #0000ff">const</span> Foo&lt;<span style="color: #0000ff">int</span>, <span style="color: #0000ff">int</span>&gt;&amp;, <span style="color: #0000ff">int</span>)</pre><br></div>
<p>可见编译器理解错了变量类型，用typedef指定一下看看，修改上面的例子：</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">struct</span> Bar {<br><br><span style="color: #0000ff">typedef</span> Foo&lt;<span style="color: #0000ff">int</span>,<span style="color: #0000ff">int</span>&gt; FooType;<br><br><span style="color: #0000ff">void</span> method( FooType <span style="color: #0000ff">const</span> &amp;stuff = FooType());<br><br>};<br></pre><br></div>
<p>编译通过！
<p>不过到底是为什么呢？
<p>先看下这么修改行不行？</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">struct</span> Bar {<br><br><span style="color: #0000ff">void</span> method( Foo&lt;<span style="color: #0000ff">int</span>,<span style="color: #0000ff">int</span>&gt; <span style="color: #0000ff">const</span> &amp;stuff = (Foo&lt;<span style="color: #0000ff">int</span>,<span style="color: #0000ff">int</span>&gt;()));<br><br>};<br></pre><br></div>
<p>加了括号，同样可以~~
<p>为了说清楚，先看一下以下的代码：</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">struct</span> Bar {<br><br><span style="color: #0000ff">void</span> method(<span style="color: #0000ff">int</span> i = j);<span style="color: #008000">//’j’ not declared yet</span><br><br><span style="color: #0000ff">static</span> <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> j = 0;<br><br>};<br></pre><br></div>
<p>这样编译是没有问题的，尽管j未声明，但编译器可以分析出j来。
<p>而编译器是这么看待我们最上面的代码的：</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">void</span> method ( Foo&lt;<span style="color: #0000ff">int</span>,<span style="color: #0000ff">int</span>&gt; <span style="color: #0000ff">const</span>&amp; stuff = Foo&lt;<span style="color: #0000ff">int</span> <span style="color: #008000">// Arg 1 with dflt.</span><br><br>, <span style="color: #0000ff">int</span>&gt;() ); // Arg 2 - syntax error</pre><br></div>
<p>这就不难理解编译器报的错误了，增加了一对括号可以保证编译器理解正确。
<p>同时，The following case shows an example where <b>g++</b> succeeds but <b>Comeau</b> still generates a syntax error:</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">template</span>&lt;<span style="color: #0000ff">int</span> J, <span style="color: #0000ff">int</span> K&gt;<br><br><span style="color: #0000ff">class</span> Foo { };<br><br><span style="color: #0000ff">struct</span> Bar {<br><br><span style="color: #0000ff">void</span> method ( Foo&lt;0, 0&gt; <span style="color: #0000ff">const</span> &amp; i = ( Foo&lt;j, k&gt; () ) );<br><br><span style="color: #0000ff">static</span> <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> j = 0;<br><br><span style="color: #0000ff">static</span> <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> k = 0;<br><br>};<br></pre><br></div>
<p>继续延伸一下，为什么多参数的函数调用放在同样的位置不会出错呢？比如：</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">int</span> foo(<span style="color: #0000ff">int</span>,<span style="color: #0000ff">int</span>,<span style="color: #0000ff">int</span>);<br><br><span style="color: #0000ff">struct</span> Bar {<br><br><span style="color: #0000ff">void</span> method(<span style="color: #0000ff">int</span> i = foo(0,0,0));<br><br>};<br></pre><br></div>
<p>因为编译器是这么理解上面的代码的：</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">int</span> foo (<span style="color: #0000ff">int</span>, <span style="color: #0000ff">int</span>, <span style="color: #0000ff">int</span>);<br><br><span style="color: #0000ff">struct</span> Bar {<br><br><span style="color: #0000ff">void</span> method ( <span style="color: #0000ff">int</span> j =<br><br>foo (0, 0, 0) ); <span style="color: #008000">// Comma's here are inside ( )</span><br><br>};<br></pre><br></div>
<p>为什么编译器在这里理解对了呢？其实不难猜测，C++要求所有的括号必须配对，’(’就意味着有一个’)’在后面。但模板参数里的’&lt;’不同，C++允许对’&lt;’重载。
<p>The reason for the problem here is that '&lt;' does not need to be matched, since it is overloaded in C++ and so can be the less than operator or<b> the start of a template argument list</b>.
<p>看下这个例子就明白了：</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">template</span>&lt;<span style="color: #0000ff">int</span> I, <span style="color: #0000ff">int</span> J&gt;<br><br><span style="color: #0000ff">class</span> Foo { };<br><br><span style="color: #0000ff">struct</span> Bar {<br><br><span style="color: #0000ff">template</span> &lt;<span style="color: #0000ff">typename</span> T&gt; <span style="color: #0000ff">struct</span> Y { };<br><br><span style="color: #0000ff">void</span> method ( ::Foo&lt;0,0&gt; <span style="color: #0000ff">const</span>&amp; stuff = Foo&lt;10 , Y &lt; <span style="color: #0000ff">int</span> &gt; = Y&lt;<span style="color: #0000ff">int</span>&gt;() );<br><br><span style="color: #0000ff">struct</span> X {<br><br>::Foo&lt;0, 0&gt; <span style="color: #0000ff">operator</span>&lt; (<span style="color: #0000ff">int</span>);<br><br>};<br><br><span style="color: #0000ff">static</span> X Foo;<br><br>};<br></pre><br></div>
<p>编译没有问题，因为这里没有什么默认模板参数，实际上是两个参数。。。。。。
<img src ="http://www.cppblog.com/izualzhy/aggbug/162055.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-12-13 21:41 <a href="http://www.cppblog.com/izualzhy/archive/2011/12/13/162055.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于模板成员类型引发的错误:error: expected `;' before &amp;lsquo;iter&amp;rsquo;</title><link>http://www.cppblog.com/izualzhy/archive/2011/12/13/162054.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Tue, 13 Dec 2011 13:39:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/12/13/162054.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/162054.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/12/13/162054.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/162054.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/162054.html</trackback:ping><description><![CDATA[<p>先看一个例子：</p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #cc6633">#include</span> &lt;vector&gt;<br><br><span style="color: #0000ff">template</span>&lt;<span style="color: #0000ff">typename</span> T&gt;<br><br><span style="color: #0000ff">class</span> Foo {<br><br>};<br><br><span style="color: #0000ff">template</span>&lt;<span style="color: #0000ff">typename</span> T&gt;<br><br><span style="color: #0000ff">void</span> method()<br><br>{<br><br>std::vector&lt;Foo&lt;T&gt; &gt; vecFoo;<br><br>std::vector&lt;Foo&lt;T&gt; &gt;::iterator iter = vecFoo.begin();<br><br>}<br></pre><br></div>
<p>编译是通不过的。
<p>解决办法：
<p>typename std::vector&lt;Foo&lt;T&gt; &gt;::iterator iter = vecFoo.begin();
<p>就可以了。
<p>Effective C++:了解typename的双重意义里做了解释。
<p>需要用typename告诉解析器这是个类型，否则编译器会当做相应的静态变量来处理。比如,C是一个模板类：
<p>C::iterator* x;编译器会理解为是C的静态变量乘上x……
<img src ="http://www.cppblog.com/izualzhy/aggbug/162054.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-12-13 21:39 <a href="http://www.cppblog.com/izualzhy/archive/2011/12/13/162054.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>