【发布时间】:2016-11-28 12:10:19
【问题描述】:
来自 Lippman 等人的 C++Primer 第 5 版,第 16.1.2 节:
//forward declarations needed for friend declarations in Blob
template <typename> class BlobPtr;
template <typename> class Blob;
template <typename T> bool operator==(const Blob<T>&, const Blob<T>&)
template <typename T> class Blob {
friend class BlobPtr<T>;
friend bool operator==<T>(const Blob<T>&, const Blob<T>&);
}
第一个问题:在行中
friend bool operator==<T>(const Blob<T>&, const Blob<T>&);
为什么<T> 出现在== 之后?为什么不简单地写
friend bool operator==(const Blob<T>&, const Blob<T>&);
我添加了以下代码来定义 operator== 并实例化类模板。它成功编译并链接:
template <typename T>
bool operator==(const Blob<T> &lhs, const Blob<T> &rhs) {return true;}
int main() {
Blob<int> a, b;
a == b;
}
如果我在朋友声明中删除operator== 之后的<T>,我会收到链接器错误:
Undefined symbols for architecture x86_64: "operator==(Blob<int> const&, Blob<int> const&)", referenced from: _main in partial_blob-3ccda9.o
显然<T> 跟在operator== 后面是必须的,但为什么呢?
第二个问题:如果我想为同一个类定义关系小于运算符<,我猜我应该遵循适用于==的模式:
1) 前向声明操作符
2) 将运算符声明为朋友,插入附加的<T>,其功能我不明白
3) 定义类外的操作符。
因此我添加以下代码:
template <typename T> bool operator<(const Blob<T>&, const Blob<T>&);
template <typename T> class Blob {
//other members as before
friend bool operator<<T>(const Blob<T>&, const Blob<T>&);
}
bool operator<(const Blob<T>&, const Blob<T>&) {return true;}
int main() {
//other statements as before
a < b;
}
这会在operator<<T> 附近产生编译错误,我认为是因为编译器将<< 解释为插入运算符。但是如果我将朋友声明重写为
friend bool operator<(const Blob<T>&, const Blob<T>&);
然后我收到一个链接器错误,类似于之前== 的链接器错误:
"operator<(Blob<int> const&, Blob<int> const&)", referenced from: _main in partial_blob-a85d5d.o
我怎样才能成功地为这个类定义运算符<?
(注意:运算符必须声明为友元,因为更全面的实现依赖于私有变量。)
【问题讨论】:
-
记住这样声明的友元函数不是成员函数,它们是非成员函数,没有
<T>,函数是不完整的。至于operator<<T>,请尝试在操作员名称和模板之间添加一个空格,例如operator< <T>。 -
关于未定义的引用及其原因和解决方案(如您所知); stackoverflow.com/a/35891188/3747990
-
@JoachimPileborg - 您能否提供此语法介绍的参考?我什至不知道它叫什么,所以我很难找到它。是模板专业化吗?显式实例化?对这些字词的网络搜索没有产生有用的结果。
标签: c++ templates operator-overloading friend