你如何理解C ++中的依赖名称

时间:2009-10-06 20:12:45

标签: c++

我通常在模板的上下文中遇到这个术语“依赖名称”。但是,我很少接触后者。因此,自然希望更多地了解从属名称的概念。

您如何在模板和其他模板的上下文中理解它?这个例子受到了极大的鼓励

2 个答案:

答案 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.