【发布时间】:2021-10-30 03:43:27
【问题描述】:
我正在尝试了解模板和友谊在 C++ 中是如何工作的。所以我自己看/尝试了一些例子。下面给出了一个我无法理解的示例:
版本 1
#include <iostream>
using namespace std;
//template<typename T> void func4();
//template<typename T> class NAME;
// template<typename T> std::ostream& operator<< (std::ostream&, NAME<T> const&);
template<typename T>
class NAME {
friend void func4<T>();
friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const&);
};
int main()
{
cout << "Hello World" << endl;
return 0;
}
以上版本1报如下错误:
prog.cc:13:17: error: variable or field 'func4' declared void
13 | friend void func4<T>();
| ^~~~~
prog.cc:13:17: error: expected ';' at end of member declaration
13 | friend void func4<T>();
| ^~~~~
| ;
prog.cc:13:22: error: expected unqualified-id before '<' token
13 | friend void func4<T>();
| ^
我的第一个问题是,即使我已经评论了func4 和operator<< 模板函数的前向声明,那么我怎么才能只得到func4 的错误?这就是operator<< 没有错误的原因。
请注意,如果我们想与模板的特定实例成为朋友,我知道我们需要前向声明。那是为了
friend void func4<T>();
为了工作,我们需要注释掉语句
template<typename T> void func4();
对于
friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const&);
为了工作,我们需要在程序开始时注释掉相应的前向声明。但是当我只注释掉template<typename T> void func4(); 语句时,程序可以运行并且operator<< 没有错误。同样为什么我们没有收到operator<< 的错误,即使我没有注释掉相应的前向声明。
我的第二个问题是这样的陈述
friend void func4<T>();
同
friend void func4<>();
同样是语句
friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const&);
同
friend std::ostream& operator<< <> (std::ostream&, NAME<T> const&);
我的想法是语句friend void func4<>(); 是使用语句template <typename T> void func4(); 声明的函数模板的特化。同时,当我们编写friend void func4<T>(); 时,我们显式 传递了T,所以在这种情况下,当我们编写/调用func4<int>(); 时,函数模板func4<int> 将被实例化,然后占用内存。另一方面,专门的模板函数已经占用了一些内存,因为我们必须在调用它之前提供它的定义。那么有人可以解释一下我们使用<T> 和使用<> 时是否存在区别。总之,在我看来,在<> 的情况下,将使用用户提供的专业化,而在<T> 的情况下,当我们调用func4() 时将创建一个新的intiantion。所以存在差异,因为在<> 的情况下,我们必须提供一个已经占用一些空间(内存)的定义,而在<T> 的情况下,func4 只会在我们使用/调用它时占用空间(内存)。这是正确的结论吗?
我的第三个问题是我有read:
无法为重载运算符、转换函数和构造函数显式指定模板参数,因为它们在调用时不使用函数名。
根据上面引用的语句,我们不能显式地为重载运算符指定模板参数,但是如何将friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const&);写成重载运算符
【问题讨论】:
-
请格式化一下,文字墙很难阅读。
-
@HatteRooster 好的,我已经格式化了问题的第一部分和第二部分。你可以再检查一下。
-
第三个问题中的引用谈论的是使用运算符,而不是定义它。您不能通过编写
x << <some_type> z;(或您可能想到的任何其他形式)之类的内容来指定模板参数。 -
您是否已经得到了所有问题的答案?
标签: c++ c++11 templates lookup argument-dependent-lookup