这是ISO C ++标准14.6 / 8的声明:
在查找模板定义中使用的名称声明时,通常的查找规则用于非依赖名称。依赖于模板参数的名称查找被推迟,直到知道实际模板参数(14.6.2)。
示例:
#include <iostream>
using namespace std;
template<class T> class Set {
T* p;
int cnt;
public:
Set();
Set<T>(const Set<T>&);
void printall()
{
for (int i = 0; i<cnt; i++)
cout << p[i] << ’\n’;
}
// ...
};
在示例中,i是我在printall中声明的局部变量,cnt是在Set中声明的成员cnt,cout是在iostream中声明的标准输出流。但是,不是每一个声明都可以这样找到;必须推迟一些名称的解析,直到知道实际的模板参数。例如,即使名称运算符&lt;&lt;在printall()的定义中已知,并且可以在运算符的实际声明中找到它的声明&lt;&lt;需要打印p [i]直到知道T是什么类型才能知道(14.6.2)。
我无法理解这一点......以及这个例子呢?
任何人都可以告诉另一个这样的例子......请
答案 0 :(得分:2)
只看模板,你能告诉我p[i]
的类型是什么吗?不会。p[i]
中的Set<int>
类型为int
; p[i]
中Set<std::string>
的类型将为std::string
。因此,operator<<
的查找必须延迟,直到模板被实例化并且p[i]
的类型已知。
你有一个类似的问题(假设这是Set<T>
的另一个成员)
// In Set<T>
void reverse()
{
for (int i = 0; i <= cnt-i; ++i)
{
using std::swap;
swap(p[i], p[cnt-i]);
}
}
交换的查找也需要p[i]
的类型,即使前面有一个使用声明。
答案 1 :(得分:0)
T* p;
...
for (int i = 0; i<cnt; i++)
cout << p[i] << ’\n’;
基本上,在知道类型cout << p[i] << ’\n’;
T
是否为有效表达式(例如)
答案 2 :(得分:0)
模板具有dependent name
和non-dependent name
的概念。简而言之,从属名称是以某种方式依赖于模板参数的名称。在代码'T * p'中,使'p'成为依赖名称,因为它取决于模板参数T
现在cout << p[i]
需要重载operator <<
,如此
ostream& operator << (ostream &os, T const &t);
或operator <<
的重载,可以转换'T'。
但这样的过载是否可用?在“T”已知之前,编译器如何知道这一点?
这正是标准上述引用的内容。
诸如'i'等名称是非依赖的,因为它们不以任何方式依赖于模板参数。因此,即使'T'未知
,也可以立即解析这些非依赖名称的查找