Ответ 1
Поскольку value
является неквалифицированным именем, а во время первого этапа поиска имени компилятор не имеет понятия, что это элемент данных, унаследованный от базового класса (он еще не создал экземпляр Base<T>
). Таким образом, он будет искать глобальное пространство имен и не найдет переменной с именем value
; следовательно, он выдаст ошибку.
Вот типичный подход для решения этой проблемы:
template <class T>
struct Derived : public Base<T> {
int getValue() { return this->value; }
// ^^^^^^
};
По правде говоря, разыменование this
сообщает компилятору, что последующее имя - это имя (возможно, унаследованного) элемента данных, и поиск должен быть отложен до того момента, когда функция-член фактически создается. Конечно, ваше решение:
return Base<T>::value;
В равной степени хорошо, потому что он также сообщает компилятору, что value
наследуется от базового класса Base<T>
.
Что касается вывода из Base<std::string>
, то компилятор может сразу перейти и посмотреть, содержит ли Base<std::string>
элемент данных с именем value
(поскольку он не зависит от какого-либо параметра шаблона), и если это так, он сможет определить, что выражение хорошо сформировано.
Однако, если ваш базовый класс Base<T>
, где T
неизвестен во время первой фазы поиска имени, компилятор не может определить, что value
(специализации Base
для разных T
может даже не иметь value
вообще).
Пункт 14.6/3 стандарта С++ 11:
В определении шаблона класса или класса, если базовый класс зависит от шаблона-параметра, базовый класс область не рассматривается при поиске неквалифицированного имени либо в точке определения шаблона класса или член или во время создания шаблона или члена класса. [...] [Пример:
struct A { struct B { / ... / }; int a; int Y; }; int a; template<class T> struct Y : T { struct B { / ... / }; B b; // The B defined in Y void f(int i) { a = i; } // ::a Y* p; // Y<T> }; Y<A> ya;
Члены
A::B
,A::a
иA::Y
аргумента шаблонаA
не влияют на привязку имен вY<A>
. -end пример]