友元模板函数的正确语法
Correct syntax for friend template function
在 The C++ Programming Language, Fourth Edition - chapter 23.4.7 Friends 中,我找到了以下示例(我对其进行了轻微修改以仅显示相关部分):
template<typename T>
class Vector {
public:
friend Vector operator*<>(const Vector& v, int f);
^^ ~~~~ ?
};
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f) {
return v;
}
我试图编译它,但出现以下错误 (clang):
main.cpp:8:20: error: friends can only be classes or functions
friend Vector operator*<>(const Vector& v, int f);
^
main.cpp:8:29: error: expected ';' at end of declaration list
friend Vector operator*<>(const Vector& v, int f);
^
;
2 errors generated.
本书解释说:
The <> after the name of the friend function is needed to make clear that the friend is a template function. Without the <>, a non template function would be assumed.
这就是全部。
如果没有 <>
,此代码可以编译,但是当使用运算符*时(例如:Vector<int> v; v*12;
),则会出现链接器错误:
main.cpp:(.text+0xb): undefined reference to `operator*(Vector<int> const&, int)'
所以我假设需要 <>
来告诉编译器每次为给定类型实例化 Vector 模板时都应该生成 operator* 的函数模板。
但是我在书中的示例中做错了什么,为什么?
正如书上所说,
the <>
after the name of the friend function is needed to make clear that the friend is a template function.
也就是说,这个名字应该引用一个函数模板,这个函数模板应该提前声明(作为模板)。例如
// forward declaration of the class template
template<typename T>
class Vector;
// declaration of the function template
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f);
template<typename T>
class Vector {
public:
// friend declaration
friend Vector operator*<>(const Vector& v, int f);
};
// definition of the function template
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f) {
return v;
}
在您的情况下,您直接在 Vector
中 声明 operator*
为朋友,而没有任何事先声明。因此正确的语法是:
template<typename T>
class Vector {
public:
template<typename>
friend Vector operator*(const Vector& v, int f);
};
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f) {
return v;
}
要使模板友元方法语法正常工作,您需要对此模板方法进行前向声明。
template<typename T>
class Vector;
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f);
template<typename T>
class Vector
{
template<typename T_> friend
Vector<T_> operator*(const Vector<T_>& v, int f);
};
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f)
{
return v;
}
无论您使用的是什么书,都对它进行了错误的解释。
你需要做的是
template<typename T>
class Vector
{
public:
friend Vector<T> operator*(const Vector<T>& v, int f);
};
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f)
{
return v;
}
以上使得接受 Vector<T>
的 operator*()
成为 Vector<T>
的朋友但不是 Vector<U>
的朋友(除非 T
是相同的输入 U
).
在 class 定义中,可以从 Vector<T>
中省略 <T>
,但根据我的经验,人类似乎更难以说服自己函数声明和函数定义相互对应。所以我一般不喜欢那样做......不过你的电话。
显式特化模板时使用 <>
语法,但这不是您想要做的。例如,使用模板函数;
template <class T> void foo(T) { /* whatever */ }
template<> void foo<int> {/* something specific to int */ }
使用 <>
也是 C++ FAQ suggests。
但是您可以像往常一样简单地使用模板化声明来解决它,除了参数的命名必须与 class 参数不同。然后在单独的定义中,您可以再次使用任何类型名称:
template <typename T>
class Vector {
public:
T i{};
// Typename must be different from the class typename(s).
template <typename T_1>
friend ostream& operator<<(ostream& os, const Vector<T_1>& v);
};
// Typename can be any.
template <typename T>
ostream& operator<<(ostream& os, const Vector<T>& v) {
return os << v.i;
}
就是这样。不需要奇怪的 <>
中间函数声明或预声明。
在 The C++ Programming Language, Fourth Edition - chapter 23.4.7 Friends 中,我找到了以下示例(我对其进行了轻微修改以仅显示相关部分):
template<typename T>
class Vector {
public:
friend Vector operator*<>(const Vector& v, int f);
^^ ~~~~ ?
};
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f) {
return v;
}
我试图编译它,但出现以下错误 (clang):
main.cpp:8:20: error: friends can only be classes or functions
friend Vector operator*<>(const Vector& v, int f);
^
main.cpp:8:29: error: expected ';' at end of declaration list
friend Vector operator*<>(const Vector& v, int f);
^
;
2 errors generated.
本书解释说:
The <> after the name of the friend function is needed to make clear that the friend is a template function. Without the <>, a non template function would be assumed.
这就是全部。
如果没有 <>
,此代码可以编译,但是当使用运算符*时(例如:Vector<int> v; v*12;
),则会出现链接器错误:
main.cpp:(.text+0xb): undefined reference to `operator*(Vector<int> const&, int)'
所以我假设需要 <>
来告诉编译器每次为给定类型实例化 Vector 模板时都应该生成 operator* 的函数模板。
但是我在书中的示例中做错了什么,为什么?
正如书上所说,
the
<>
after the name of the friend function is needed to make clear that the friend is a template function.
也就是说,这个名字应该引用一个函数模板,这个函数模板应该提前声明(作为模板)。例如
// forward declaration of the class template
template<typename T>
class Vector;
// declaration of the function template
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f);
template<typename T>
class Vector {
public:
// friend declaration
friend Vector operator*<>(const Vector& v, int f);
};
// definition of the function template
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f) {
return v;
}
在您的情况下,您直接在 Vector
中 声明 operator*
为朋友,而没有任何事先声明。因此正确的语法是:
template<typename T>
class Vector {
public:
template<typename>
friend Vector operator*(const Vector& v, int f);
};
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f) {
return v;
}
要使模板友元方法语法正常工作,您需要对此模板方法进行前向声明。
template<typename T>
class Vector;
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f);
template<typename T>
class Vector
{
template<typename T_> friend
Vector<T_> operator*(const Vector<T_>& v, int f);
};
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f)
{
return v;
}
无论您使用的是什么书,都对它进行了错误的解释。
你需要做的是
template<typename T>
class Vector
{
public:
friend Vector<T> operator*(const Vector<T>& v, int f);
};
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f)
{
return v;
}
以上使得接受 Vector<T>
的 operator*()
成为 Vector<T>
的朋友但不是 Vector<U>
的朋友(除非 T
是相同的输入 U
).
在 class 定义中,可以从 Vector<T>
中省略 <T>
,但根据我的经验,人类似乎更难以说服自己函数声明和函数定义相互对应。所以我一般不喜欢那样做......不过你的电话。
显式特化模板时使用 <>
语法,但这不是您想要做的。例如,使用模板函数;
template <class T> void foo(T) { /* whatever */ }
template<> void foo<int> {/* something specific to int */ }
使用 <>
也是 C++ FAQ suggests。
但是您可以像往常一样简单地使用模板化声明来解决它,除了参数的命名必须与 class 参数不同。然后在单独的定义中,您可以再次使用任何类型名称:
template <typename T>
class Vector {
public:
T i{};
// Typename must be different from the class typename(s).
template <typename T_1>
friend ostream& operator<<(ostream& os, const Vector<T_1>& v);
};
// Typename can be any.
template <typename T>
ostream& operator<<(ostream& os, const Vector<T>& v) {
return os << v.i;
}
就是这样。不需要奇怪的 <>
中间函数声明或预声明。