Директива «Using» не работает в шаблоне - PullRequest
4 голосов
/ 22 декабря 2010

Я понимаю, что имена членов шаблона базового класса скрыты в области видимости производного класса и поэтому должны быть доступны с использованием this->foo или Base<T>::foo.Однако я напоминаю, что C ++ также позволяет вам использовать ключевое слово using, которое может пригодиться в функции производного класса, которая часто обращается к переменной базового класса.Поэтому, чтобы не загромождать функцию с помощью this-> везде, я бы хотел использовать ключевое слово using.

Я знаю, что делал это раньше, но по любой причине могуне заставить его работать сейчас.Я, вероятно, просто делаю что-то глупое, но следующий код не скомпилируется:

template <class T>
struct Base
{
   int x;
};

template <class T>
struct Derived : public Base<T>
{
   void dosomething()
   {
     using Base<T>::x; // gives compiler error
     x = 0;
   }
};

int main()
{
   Derived<int> d;
}

Ошибка (с GCC 4.3): error: ‘Base<T>’ is not a namespace

Почему неэто работа?

Ответы [ 3 ]

7 голосов
/ 22 декабря 2010

Это не работает, потому что язык C ++ не имеет такой возможности и никогда не имел.Объявление-использование для члена класса должно быть объявлением члена .Это означает, что вы можете использовать только в области видимости класса, но никогда не в локальной области видимости.Все это не имеет абсолютно никакого отношения к шаблонам.

Другими словами, вы можете поместить ваше объявление об использовании в область видимости класса

struct Derived : public Base<T> {
  ...
  using Base<T>::x;
  ...
};

, но вы не можете иметь его внутри функции.

Использование-объявлений для членов пространства имен может быть помещено в локальную область, но использование-объявлений для членов класса не может быть.Вот почему сообщение об ошибке жалуется на то, что Base<T> не является пространством имен.

3 голосов
/ 22 декабря 2010

Вне области действия класса (если вы находитесь в блоке и т. Д.), Вы можете только именовать членов пространства имен в объявлении использования.

Если вы не хотите помещать это использование декларации в область действия Derived (что является ИМО выгодным решением), другой вариант - использовать ссылку

int &x = this->x;
x = 0;

Следует отметить, что это семантически отличается, поскольку оно

  • заставляет существовать определение для Base<T>::x, что может не иметь места для статических членов-данных const
  • Forces Base<T>::x должен иметь тип int& или быть конвертируемым в тип int&.

В противном случае, если вы хотите избежать повторного использования this->, я не вижу других вариантов.

3 голосов
/ 22 декабря 2010
template <class T>
struct Base
{
   int x;
};

template <class T>
struct Derived : public Base<T>
{
   using Base<T>::x;
   void dosomething()
   {
     x = 0;
   }
};

int main()
{
   Derived<int> d;
}

Как говорили другие, работает только класс.

...