为什么我允许跳过模板参数(参见评论)?为什么我会收到链接错误?
template <typename T>
class Number {
public:
Number(int val) {}
// Why can I skip template arguments here?
friend Number operator* (Number first, Number second);
};
template<typename T>
Number<T> operator* (Number<T> lhs, Number<T> rhs) {
return Number<T>(42);
}
int main() {
Number<int> num1(22), num2(23);
Number<int> res = num1 * num2;
}
答案 0 :(得分:3)
只有在其名称出现在该类的范围内时,才能省略类模板的模板参数。因此,您的friend
声明隐含地需要两个Number<T>
参数,但请注意它是不模板。
由于它不是模板,因此您在T
的实例化中指定的两个Number<T>
参数中的int
实际上是num1
num2
。因此,您的friend
声明实际上是:
friend Number operator* (Number<int> first, Number<int> second);
Number
下面的函数模板的定义是一个单独的重载,而不是您声明为朋友的重载。这是因为第一个是带有两个Number<int>
的常规函数,而第二个是可以用任何Number<T>
实例实例化的函数模板。由于它是一个单独的重载,因此不是Number
的朋友,因此无法访问Number
的私人/受保护成员。
num1 * num2
选择呼叫您的常规朋友功能,因为两个参数完全匹配。由于尚未定义该函数,因此您将收到未定义的引用。
答案 1 :(得分:0)
因为您处于模板类的范围内。
该类使用type参数进行实例化,并且在该范围内,名称Number
实际上是Number<T>
,其分配器类型为T。
请注意,构造函数也不需要模板参数。
Number的friend运算符将实例化为:
friend Number<int> operator* (Number<int> first, Number<int> second);