C++ 为什么通用模板方法定义没有';与模板类专门化不匹配?
我有以下代码:C++ 为什么通用模板方法定义没有';与模板类专门化不匹配?,c++,templates,c++11,C++,Templates,C++11,我有以下代码: template <class T, class U = T> class A { public: void f(); }; template <class T> class A<T, T> { public: void f(); // Unaltered method. // Some differences. }; template <class T, class U> void A<
template <class T, class U = T>
class A {
public:
void f();
};
template <class T>
class A<T, T> {
public:
void f(); // Unaltered method.
// Some differences.
};
template <class T, class U>
void A<T, U>::f() {}
int main() {
A<int> a;
a.f();
return 0;
}
模板
甲级{
公众:
无效f();
};
模板
甲级{
公众:
void f();//未更改的方法。
//有些差异。
};
模板
void A::f(){}
int main(){
A A;
a、 f();
返回0;
}
clang++-std=c++11 test.cc
给了我一个错误:对'A::f()'的引用未定义。
为什么提供的方法
f()
的定义不适用于类A
?主要类模板模板类A
和部分专业化模板类A
是两个不同的模板定义。定义它们之后,无论何时引用类模板名称A
,都将始终考虑主模板和所有部分专门化
无论何时使用单个模板参数或两个相同类型的参数实例化A
,它都会更好地匹配您提供的专门化,并且不考虑主模板
在您的示例中,由于您提供了部分专门化,如果您尝试使用单个模板参数或两个相同类型的模板参数实例化A
,则无论默认模板参数如何,都无法匹配主模板
当然,解决方案是为A::f()
模板
void A::f(){}
编辑:在存在部分专业化的情况下,匹配它们的规则由(N3797)§14.5.5.1/1[temp.class.spec.match]给出 在需要 实例化类时,有必要确定 实例化将使用主模板或其中一个模板生成 部分专业化。这是通过匹配模板来完成的 类模板专用化与模板的参数 部分专门化的参数列表。
如果恰好找到一个匹配的专门化,则从该专门化生成实例化。
如果找到多个匹配专门化,则使用偏序规则(14.5.5.2)确定 专业比其他专业更专业。。。
如果未找到匹配项,则从主模板生成实例化
在您的示例中,第一条规则适用,编译器甚至没有使用第三条规则。当您在类之外定义类模板的成员函数时,您只是为类模板中声明的相应函数定义函数。您没有创建可能与其他参数匹配的新函数模板。在您的示例中:
template <class T, class U = T>
class A {
public:
void f(); // This is the declaration of A<T,U>::f()
};
template <class T>
class A<T, T> {
public:
void f(); // This is the declaration of A<T,T>::f()
};
template <class T, class U>
void A<T, U>::f() {} // This is the definition of A<T,U>::f()
// There is no definition of A<T,T>::f()
模板
甲级{
公众:
void f();//这是A::f()的声明
};
模板
甲级{
公众:
void f();//这是A::f()的声明
};
模板
void A::f(){}//这是A::f()的定义
//没有A::f()的定义
我相信您的想法是,编译器将看到您正在调用
A::f()
,并将查看成员函数定义并找到一个匹配的,但实际情况并非如此。编译器总是通过类模板查找要调用的函数,一旦找到匹配项,就会查找相应的定义。在您的例子中,您正在调用A::f()
,因此它首先查找与A
匹配的类定义,然后找到您的A
类模板专用化。它看到A
确实有一个名为f
的成员函数,它与您的函数调用相匹配,这意味着A::f()
需要实例化。要实例化A::f()
,编译器会查找A::f()
的定义,但找不到它。它只找到A::f
的定义,该定义不匹配。用于查找正确函数声明的模板参数匹配不适用。谢谢您的回答,但如果您提供编译器不考虑我的定义的更多详细信息,那就太好了-据我所知,该定义是一个不同的模板,应该在两个类模板上匹配。我错过了什么?@Abyses.7我已经更新了答案。简短的回答是因为语言规则说只匹配部分专门化,而不匹配主要的。我不明白,但我真的想:如果类模板实例化在template void A::f(){}
-行中是必需的,那么它应该匹配void A::f(){}
,即类模板的专门化,应该没有问题。也许吧,我们可以聊一聊吗?@Abysis.7在聊天中我再也解释不清楚了。我上面引用的第一个要点非常明确,在您的案例中不可能匹配主模板。如果您有一个只关心第一个模板参数类型的成员函数,并且您希望主专用化和部分专用化共享此函数的实现,则可以选择创建(friend
maybe)两个类模板都可以调用的非成员函数模板。A和A有什么区别?您可能可以避免类的专门化(使用enable_if,SFINAE…。@ysdx的区别在于本地类的声明以及它在某些方法中的用法。
template <class T, class U = T>
class A {
public:
void f(); // This is the declaration of A<T,U>::f()
};
template <class T>
class A<T, T> {
public:
void f(); // This is the declaration of A<T,T>::f()
};
template <class T, class U>
void A<T, U>::f() {} // This is the definition of A<T,U>::f()
// There is no definition of A<T,T>::f()