8.5.3 使用有多个形参的类模板
要在类模板中使用多个类型形参,只需对我们刚才看到的使用单个形参的示例作简单的扩充即可。我们可以在模板定义中的任何位置使用各个类型形参。例如,我们可以定义一个使用两个类型形参的类模板:
- template<class T1, class T2>
- class CExampleClass
- {
- // Class data members
-
- private:
- T1 m_Value1;
- T2 m_Value2;
-
- // Rest of the template definition...
- };
上面那两个类数据成员的类型取决于我们初始化对象时为形参提供的类型。
类模板中的形参不仅仅限于数据类型。我们还可以在类定义中使用一些需要以常量或常量表达式进行替换的形参。在前面的CSamples模板中,我们随意将数组m_Values定义成包含100个元素。然而,我们还可以让该模板的用户在实例化对象时选择数组的大小,方法是将该模板定义成如下形式:
- template <class T, int Size> class CSamples
- {
- private:
- T m_Values[Size]; // Array to store samples
- int m_Free; // Index of free location in m_Values
-
- public:
- // Constructor definition to accept an array of samples
- CSamples(const T values[], int count)
- {
- m_Free = count < Size count:Size; // Don't exceed the array
-
- for(int i = 0; i < m_Free; i++)
- m_Values[i] = values[i]; // Store count number of samples
- }
-
- // Constructor to accept a single sample
- CSamples(const T& value)
- {
- m_Values[0] = value; // Store the sample
- m_Free = 1; // Next is free
- }
-
- // Default constructor
- CSamples()
- {
- m_Free = 0; // Nothing stored, so first is free
- }
-
- // Function to add a sample
- int Add(const T& value)
- {
- int OK = m_Free < Size; // Indicates there is a free place
- if(OK)
- m_Values[m_Free++] = value;// OK true, so store the value
- return OK;
- }
-
- // Function to obtain maximum sample
- T Max() const
- {
- // Set first sample or 0 as maximum
- T theMax = m_Free m_Values[0] : 0;
-
- for(int i = 1; i < m_Free; i++) // Check all the samples
- if(m_Values[i] > theMax)
- theMax = m_Values[i]; // Store any larger sample
- return theMax;
- }
- };
创建对象时给Size提供的数值将代替整个模板定义中该形参的所有实例。现在,我们可以像下面这样声明前面那个示例中的CSamples对象:
- CSamples<CBox, 3> MyBoxes(boxes, sizeof boxes/sizeof CBox);
因为我们可以为Size形参提供任何常量表达式,所以还可以这样写:
- CSamples<CBox, sizeof boxes/sizeof CBox>
- MyBoxes(boxes, sizeof boxes/sizeof CBox);
不过,该示例是很少见的模板用法,原来的版本更为合适。使Size成为模板形参的结果是,那些存储相同类型的对象但Size形参值不同的模板实例完全是不同的类,而且不可能被混淆。例如,CSamples<double, 10>类型的对象不能在包含CSamples<double, 20>类型对象的表达式中使用。
当实例化模板时,我们需要小心处理那些包含比较运算符的表达式。看看下面这条语句:
- CSamples<aType, x > y 10 : 20 > MyType(); // Wrong!
该语句不能正确编译,因为表达式中y前面的>被解释为右尖括号。我们应该将这条语句写成:
- CSamples<aType, (x > y 10 : 20) > MyType(); // OK
括弧确保第二个模板实参的表达式不会与尖括号混淆。