Как вы понимаете зависимые имена в С++
Я встречаю этот термин "зависимые имена", как правило, в контексте шаблонов. Однако я редко касаюсь последнего. Таким образом, естественно, хотелось бы узнать больше о концепции зависимых имен.
Как вы понимаете это в контексте шаблонов и вне их? пример критически приветствуется!
Ответы
Ответ 1
Зависимое имя по существу является именем, которое зависит от аргумента шаблона.
При использовании шаблонов существует различие между точкой определения шаблона и точкой создания экземпляра, т.е. где вы фактически используете шаблон. Имена, которые зависят от шаблона, не привязываются до момента создания экземпляра, тогда как имена, которые не привязаны к точке определения.
Простым примером может быть:
template< class T > int addInt( T x )
{
return i + x.toInt();
}
где объявление или определение i
должно появиться перед определением, приведенным выше, поскольку i
не зависит от аргумента шаблона T
и поэтому привязано к точке определения. Определение члена toInt
переменной x
как бы неизвестного типа должно появляться только до того, как функция addInt
фактически используется где-то, поскольку она является зависимым именем (технически точка инстанцирования принимается как ближайшую охватывающую область глобального или пространства имен непосредственно перед точкой использования, и поэтому она должна быть доступна до этого).
Ответ 2
Зависимые имена характеризуются зависимостью в аргументе шаблона. Тривиальный пример:
#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;
}
EDIT. Как я уже упоминал в комментарии ниже, это пример необычной ситуации, касающейся использования зависимых имен, которые появляются довольно часто. Иногда правила, регулирующие использование зависимых имен, не могут инстинктивно ожидать.
Например, если у вас есть зависимый класс, который получается из базы зависимых, но в пределах области, в которой имя из базового класса, по-видимому, не зависит от шаблона, вы можете получить ошибку компилятора, как показано ниже.
#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.