我正在学习C ++概念 - 模板专业化和部分模板专业化。有一个如下的代码,我想了解,所以我正确地得到了这些概念。
我对此几乎没有任何疑问,这些问题在下面列出:
template <typename T, int nSize>
class Buffer
{
private:
T m_atBuffer[nSize];
public:
T* GetBuffer()
{
return m_atBuffer;
}
T& operator[](int nIndex)
{
return m_atBuffer[nIndex];
}
};
template <typename T, int nSize>
void PrintBufferString(Buffer<T, nSize> &rcBuf)
{
std::cout << rcBuf.GetBuffer() << std::endl;
}
void PrintBufferString(Buffer<char, 10> &rcBuf)
{
std::cout << rcBuf.GetBuffer() << std::endl;
}
int main()
{
// declare a char buffer
Buffer<char, 13> cChar10Buffer;
// copy a value into the buffer
strcpy(cChar10Buffer.GetBuffer(), "Ten");
PrintBufferString(cChar10Buffer); //This prints "Ten"
// declare an int buffer
Buffer<int, 10> cInt10Buffer;
// copy values into the buffer
for (int nCount=0; nCount < 10; nCount++)
cInt10Buffer[nCount] = nCount;
PrintBufferString(cInt10Buffer); // This prints address of the buffer- m_atBuffer for object cInt10Buffer
return 0;
}
因此,如果我们将除char之外的任何类型传递给模板化函数PrintBufferString(),那么cout将打印缓冲区的地址而不是字符串,这是一个问题。
所以为了解决这个问题,它说我们定义了一个模板特化,如下所示,以确保只有char类型的数组可以传递给PrintBufferString()
void PrintBufferString(Buffer<char, 10> &rcBuf)
{
std::cout << rcBuf.GetBuffer() << std::endl;
}
问题1:因此,为函数PrintBufferString()添加此模板特化,我认为在我尝试调用时它应该给出了编译错误
PrintBufferString(cInt10Buffer)通过传递带有模板化类型参数int的Buffer对象,但它编译得很好?那个怎么样?那么为char类型添加这个模板特化有什么用呢?
我想为类型char添加模板特化,我们不能为任何其他类型调用它
问题2:然后我在main中添加了另一个函数调用:
Buffer<char, 11> cChar11Buffer;
strcpy(cChar11Buffer.GetBuffer(), "Eleven");
PrintBufferString(cChar11Buffer); //
它说这会产生编译错误,但它在MS -Visual C ++ 2010 Express中编译得很好。即使执行得很好并打印“十”“一些地址”“十一”。
为什么编译和执行正常?因为我已经理解类型的缓冲区与类缓冲区和函数的不同 PrintBufferString()接受类型为Buffer的对象,这两个都不能混用?
问题3:然后继续定义如下的部分模板特化,以处理类型为char但任何大小的对象缓冲区可以传递Class对象类型的情况,然后传递到函数PrintBufferString();
template<int nSize>
void PrintBufferString(Buffer<char, nSize> &rcBuf)
{
std::cout << rcBuf.GetBuffer() << std::endl;
}
现在它也像以前一样打印“十”“十一”。那么这个部分模板专业化有什么特别之处呢?这不是部分模板专业化的好例子吗?从这个例子来看,这个概念对我来说并不是很清楚。
答案 0 :(得分:2)
C ++没有/支持功能模板的部分特化,只支持类模板。因此,您所看到的代码都与您(至少是您)想要学习/理解的内容无关。
部分专业的类模板将是这样的:
template <class T, class U> // the "base" (unspecialized) template
class X {
};
template <class T> // partial specialization for `X<whatever, int>`
class X<int> {
};
请注意(如此处)非专业化模板必须位于部分专用模板之前。
答案 1 :(得分:1)
在你的第一种情况下,该功能不是专业化,它只是重载。
如果你想要阻止除char之外的其他类型,只需定义问题3中的版本。只要你没有通过模板&lt;&gt;为函数添加前缀,就不会将其视为部分特化。
您可以定义使用带有一些固定模板参数的模板类型的函数。