尝试编译这段代码会导致错误。
template <typename T>
struct MyClass;
template <typename T, std::size_t sz>
struct MyClass<T> {
static void print() {
std::cout << "Partially specialized" << std::endl;
}
};
错误:无法通过局部专业化推导模板参数
尝试推论sz
解决了这个问题。例如:
template <typename T, std::size_t sz>
struct MyClass<T[sz]> {
static void print() {
std::cout << "Partially specialized" << std::endl;
}
};
我的问题是,编译器如何解释这样的程序?不允许具有第一个结构的背后的合理原因是什么?
进一步说明:
我在想,如果初始代码是可编译的,我们可以采用诸如MyClass<int, 4>::print()
之类的方式使用它。
答案 0 :(得分:1)
在C ++中,我们声明了模板后,可以根据需要对其进行专门化处理,例如:
template <typename T> foo;
template <typename U> foo<U*>;
现在,编译器将期望对指针类型使用不同的定义。但是-专业化实际上需要专业化-它不能像原始声明那样通用。就您而言,您正在添加模板参数。甚至不关乎扣减,而是您无能为力。
因此,如果您查看错误消息other compiles give you:
(clang:)
<source>:7:8: error: class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list
struct MyClass<T> {
^ ~~~
<source>:6:1: error: too many template parameters in template redeclaration
template <typename T, std::size_t sz>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(MSVC:)
<source>(11): error C2753: 'MyClass<T>': partial specialization cannot match argument list for primary template
<source>(11): error C2764: 'sz': template parameter not used or deducible in partial specialization 'MyClass<T>'
您将看到错误消息措辞上的不同焦点:您必须专长,但不是。
另一方面,在第二个代码段中,您 专门研究:现在,您并没有为所有类型MyClass
定义T
,而仅是为一定数量的元素。您应该真正考虑一下:
template <typename U, std::size_t sz>
struct MyClass<U[sz]> {
static void print() {
std::cout << "Partially specialized" << std::endl;
}
};
因此,专门化是针对T
的形式为U[sz]
的情况。
答案 1 :(得分:1)
我在想,如果初始代码是可编译的,我们可以采用诸如
MyClass<int, 4>::print()
之类的方式使用它。
这不是模板专门化的工作方式。如果将基本模板声明为template <class T> struct MyClass
,则MyClass
仅可以使用一个模板类型参数实例化。不能将其实例化为MyClass<int, int>
或MyClass<int, 3>
或MyClass<3>
。
模板专业化可以仅对基本模板参数进行专业化。
回到您的问题。因此MyClass
可以像这样被实例化:MyClass<int>
,MyClass<float>
,MyClass<SomeClass>
,MyClass<int*>
,MyClass<int[10]>
,依此类推。 >
写作时
template <typename T, std::size_t sz>
struct MyClass<T[sz]> {
您将模板MyClass<T>
专用于数组或任何大小的任何T
。例如MyClass<int[24]>
将使用这种专业化。
撰写时
template <typename T, std::size_t sz>
struct MyClass<T> {
// ^
// no sz here
这看起来像是MyClass
的专业化,但不是,因为sz
没有出现在专业化参数中。