爱家也爱友 發表於 2026-1-26 09:41:00

模板的优化

<h2 id="嵌套时比如printvectorvectorint中的的优化">嵌套时(比如printVector&lt;vector&lt;int&gt;&gt;)中的"&gt;&gt;"的优化</h2>
<p>在使用<code>vector&lt;int&gt;</code>时,本意是向模板中传入一个<code>vector&lt;int&gt;</code>类型的参数,但是编译器错误的将"&gt;&gt;"识别为右移运算符,而不是模板参数表的结束。之前的解决方案是在"&gt;&gt;"中间添加空格"&gt; &gt;"。</p>
<p>C++11优化了这一问题,使得不添加空格也可以正确的编译。</p>
<pre><code class="language-c++">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

template&lt;typename T&gt;
class Base {
public:
        void printVector(T&amp; t) {
                auto it = t.begin();
                for (; it != t.end(); it++) {
                        cout &lt;&lt; *it &lt;&lt; " ";
                }
                cout &lt;&lt; endl;
        }
};

int main() {
        vector&lt;int&gt; v{ 1,2,3,4,5,6,7,8,9 };
        Base&lt;vector&lt;int&gt;&gt; b;
        b.printVector(v);
   
        system("pause");
        return 0;
}
</code></pre>
<p>在c++11之前会报error:</p>
<pre><code class="language-c++">test.cpp:25:20: error: '&gt;&gt;' should be '&gt; &gt;' within a nested template argument list
   Base&lt;vector&lt;int&gt;&gt; b;
</code></pre>
<p>根据错误提示中描述模板的两个右尖括之间需要添加空格,这样写起来就非常的麻烦。</p>
<p>C++11改进了编译器的解析规则,尽可能地将多个右尖括号(&gt;)解析成模板参数结束符,方便我们编写模板相关的代码。</p>
<p>上面的这段代码,在支持C++11的编译器中编译是没有任何问题的。</p>
<h2 id="方法的默认模板参数">方法的默认模板参数</h2>
<p>在c++11之前,类模板可以有默认的模板参数;但是方法模板不支持有默认的模板参数。</p>
<p>在C++11中添加了对函数模板默认参数的支持。</p>
<pre><code class="language-c++">#include &lt;iostream&gt;
#include &lt;typeinfo&gt;

using namespace std;

template&lt;typename T = int, T t = 520&gt;//c++11之前就 支持类模板 默认的模板参数,还定义了非类型参数t的默认值为520
class Test {
public:
        void print() {
                cout &lt;&lt; "current value:" &lt;&lt; t &lt;&lt; endl;
        }
};

template&lt;typename T1 = int,typename T2 = int&gt;
void func(T1 val1 = 'a', T2 val2 = 'b') {
        cout &lt;&lt; "val1: " &lt;&lt; val1 &lt;&lt; ",val2: " &lt;&lt; val2 &lt;&lt; endl;
}



int main() {
        Test&lt;&gt; t;
        t.print();
        Test&lt;int, 1024&gt; t2;
        t2.print();
        cout &lt;&lt; endl;

        //-------------------------------------------------------------
        //自动推导,根据传递的实参
        func('a', 'b'); //自动推导为 func&lt;char, char&gt;
        func&lt;int&gt;('a', 'b'); //显示的填了第一个模板参数,第二个自动推导为charfunc&lt;int, char&gt;
        func(1, 2); //推导为 func&lt;int, int&gt; 且默认就是int
        func(1.1, 2.2); //推导为 func&lt;double, double&gt;
        func&lt;char&gt;('a', 'b'); //第一个显示填了char,第二个自动推导为char func&lt;char, char&gt;
        func&lt;int, char&gt;('a', 'b'); //显示填了&lt;int, char&gt;   func&lt;int, char&gt;
        func&lt;char, int&gt;('a', 'b'); //显示填了&lt;char, int&gt;   func&lt;char, int&gt;
        func();//默认为int    func&lt;int, int&gt;

        system("pause");
        return 0;
}
</code></pre>
<p>输出:</p>
<pre><code class="language-c++">current value:520
current value:1024

val1: a,val2: b
val1: 97,val2: b
val1: 1,val2: 2
val1: 1.1,val2: 2.2
val1: a,val2: b
val1: 97,val2: b
val1: a,val2: 98
val1: 97,val2: 98
</code></pre>
<p>如上面代码,支持函数模板的默认参数,在使用时就可以根据传递的实参自动推导类型,写起来像普通函数一样;</p>
<p>但是类模板的默认参数,在使用时如不使用默认参数,仍然需要显示的定义类型。</p>
<p>当默认模板参数和模板参数自动推导同时使用时(优先级从高到低):</p>
<ul>
<li>如果显示的填了参数类型,使用显示的参数类型;</li>
<li>如果可以推导出参数类型则使用推导出的类型
<ul>
<li>模板参数类型的自动推导是根据模板函数调用时指定的实参进行推断的,没有实参则无法推导</li>
<li>模板参数类型的自动推导不会参考函数模板中指定的默认参数。</li>
</ul>
</li>
<li>如果函数模板无法推导出参数类型,那么编译器会使用默认模板参数</li>
<li>如果无法推导出模板参数类型并且没有设置默认模板参数,编译器就会报错。</li>
</ul><br><br>
来源:https://www.cnblogs.com/ggkx/p/19531598
頁: [1]
查看完整版本: 模板的优化