我通常在模板的上下文中遇到这个术语“依赖名称”。但是,我很少接触后者。因此,自然希望更多地了解从属名称的概念。
您如何在模板和其他模板的上下文中理解它?这个例子受到了极大的鼓励
答案 0 :(得分:11)
依赖名称本质上是一个依赖于模板参数的名称。
使用模板时,模板定义点与实例化点之间存在区别,即实际使用模板的位置。依赖于模板的名称在实例化之前不会被绑定,而名称不会在定义点被绑定。
一个简单的例子是:
template< class T > int addInt( T x )
{
return i + x.toInt();
}
i
的声明或定义需要在上面给出的定义之前出现,因为i
不依赖于模板参数T
而且是因此受限于定义点。尚未知类型toInt
变量的x
成员的定义只需要在addInt
函数实际使用之前出现,因为它是一个从属名称(从技术上讲,实例化点被视为在使用点之前的最近的封闭全局或命名空间范围,因此它必须在此之前可用。
答案 1 :(得分:9)
依赖名称的特征是模板参数上的依赖。琐碎的例子:
#include <vector>
void NonDependent()
{
//You can access the member size_type directly.
//This is precisely specified as a vector of ints.
typedef std::vector<int> IntVector;
IntVector::size_type i;
/* ... */
}
template <class T>
void Dependent()
{
//Now the vector depends on the type T.
//Need to use typename to access a dependent name.
typedef std::vector<T> SomeVector;
typename SomeVector::size_type i;
/* ... */
}
int main()
{
NonDependent();
Dependent<int>();
return 0;
}
编辑:正如我在下面的评论中提到的,这是一个关于使用依赖名称的特殊情况的例子,这种情况经常出现。有时,管理依赖名称使用的规则并不是人们本能地期望的。
例如,如果您有一个从依赖类派生的依赖类,但是在基类中的名称显然不依赖于模板的范围内,您可能会收到编译器错误,如下所示。
#include <iostream>
template <class T>
class Dependent
{
protected:
T data;
};
template <class T>
class OtherDependent : public Dependent<T>
{
public:
void printT()const
{
std::cout << "T: " << data << std::endl; //ERROR
}
};
int main()
{
OtherDependent<int> o;
o.printT();
return 0;
}
发生此错误是因为编译器不会在基类模板中查找name
,因为它不依赖于T
,因此它不是依赖名称。修复方法是使用this
或明确告知依赖基类模板:
std::cout << "T: " << this->data << std::endl; //Ok now.
std::cout << "T: " << Dependent<T>::data << std::endl; //Ok now.