我创建了4个类:
class C1 {};
class C2 {};
class C3 {};
class C4 {};
基于这些类的模板函数:
template<class T1, class T2>
T2 F() {
std::cout << "F<T1, T2>" << std::endl;
return T2();
}
template<class T>
T F();
template<>
C1 F<C1>() {
std::cout << "F<C1>" << std::endl;
return F<C3, C1>();
}
template<>
C2 F<C2>() {
std::cout << "F<C2>" << std::endl;
return F<C4, C2>();
}
这会导致编译错误:
explicit specialization 'C1 F<C1>(void)' is not a specialization of a function template
explicit specialization 'C2 F<C2>(void)' is not a specialization of a function template
然而,如果我将第一个函数F
的名称更改为另一个名称F1
:
template<class T1, class T2>
T2 F1() {
std::cout << "F<T1, T2>" << std::endl;
return T2();
}
template<class T>
T F();
template<>
C1 F<C1>() {
std::cout << "F<C1>" << std::endl;
return F1<C3, C1>();
}
template<>
C2 F<C2>() {
std::cout << "F<C2>" << std::endl;
return F1<C4, C2>();
}
或者将这些函数的返回类型改为相同的(比如 int
):
template<class T1, class T2>
int F() {
std::cout << "F<T1, T2>" << std::endl;
return 5;
}
template<class T>
int F();
template<>
int F<C1>() {
std::cout << "F<C1>" << std::endl;
return F<C3, C1>();
}
template<>
int F<C2>() {
std::cout << "F<C2>" << std::endl;
return F<C4, C2>();
}
然后编译成功,我就可以成功调用:
F<C1>();
F<C2>();
并获得预期输出:
F<C1>
F<T1, T2>
F<C2>
F<T1, T2>
问题是为什么第一个代码无法编译,但第二个和第三个代码可以编译。
在https://en.cppreference.com/w/cpp/language/function_template中,我发现:
我猜这就是为什么第三个代码可以编译,因为返回类型相同。但它并不能解释为什么第一个代码由于返回类型不同而无法编译。具有相同返回类型和相同参数列表的两个函数模板是不同的,并且可以通过显式模板参数列表进行区分。
即使是因为返回类型不能不同,也不能解释为什么第二个代码可以编译,因为
F<C1>
和F<C2>
在那里具有不同的返回类型。
"... is not a specialization of ..."
错误,而是在实际调用F<C1>()
和F<C2>()
时出现了"undefined reference to ..."
。 - Remy Lebeau