C++ C++;类模板专门化问题

C++ C++;类模板专门化问题,c++,templates,specialization,template-specialization,C++,Templates,Specialization,Template Specialization,通过查看以下代码,我被第3行搞糊涂了。 第3行不是基本模板的特例,它更像是一个“类重载”。但它可以成功编译。 第7行的obj1是根据第3行定义的,但编译失败。 为什么会这样? template<typename S,int T, void(* U)()> class Bar{}; // Base template template<int T, void(* U)()> class Bar<double, T, U>{}; // Specialization

通过查看以下代码,我被第3行搞糊涂了。
第3行不是基本模板的特例,它更像是一个“类重载”。但它可以成功编译。
第7行的obj1是根据第3行定义的,但编译失败。
为什么会这样?

template<typename S,int T, void(* U)()> class Bar{};  // Base template
template<int T, void(* U)()> class Bar<double, T, U>{}; // Specialization, which is good
template<int T, void(* U)()> class Bar<double, U, T>{}; // Also good, how come?

void func(){};
int main(){
   //Bar<double, func, 1> obj1;   // Error, from line 3
}
模板类栏{};//基础模板
模板类栏{};//专业化,这是好的
模板类栏{};//还不错,怎么会呢?
void func(){};
int main(){
//Bar obj1;//错误,来自第3行
}

只要该表单不在任何地方使用,编译器就不会抱怨。如果它被使用,并且编译器必须实例化,那么它会抱怨。这就是为什么如果您取消注释,就会出现错误-此时,编译器会看到有缺陷的部分专门化。

模板是特殊的:您不使用的任何东西实际上都不会实例化(编译)。这允许使用某些通用模板完成许多很酷的事情。例如,可以定义不使用某些类型参数编译的成员函数,但只要不使用这些成员,就不会出错


这也会对你造成伤害:第3行实际上格式不好——它是Bar的一个非编译专门化——但你不会注意到它,除非你在main()函数中真正尝试使用它。

那么编译器什么时候应该抱怨,什么时候不应该抱怨?如果我在第4行添加另一行:模板类栏{};它没有被使用,编译器也没有实例化,但编译失败。@John,正如我所说,如果您试图声明该类型的实例(如在取消注释
obj1
行中),它会抱怨(此时它试图实例化)。如果你不这样做,那就不会了-这就是模板的优点…@John,那是另一个问题-你有比
Bar
需要的更多的模板参数。谢谢。我会照例记住的。但是仍然觉得这个规则没有意义:)如果你有一个永远不能使用的模板,编译器可以(但不是必须)抱怨。这可能是其中之一。谢谢你的回答。请看下面我对Nim的评论。