Чтобы добавить к ответу Stevela , проблема с исходным кодом заключается в том, что вы ссылаетесь на члена, но само объявление об использовании не является объявлением члена:
7.3.3 / 6 имеет:
Объявление использования для члена класса
должна быть декларацией участника.
Чтобы подчеркнуть это, работает следующий пример:
class Sample
{
public:
enum Colour { RED,BLUE,GREEN};
};
class Derived : public Sample
{
public:
using Sample::Colour; // OK
};
Наконец, как указал Игорь Семенов здесь , даже если вы переместите определение enum в пространство имен, тем самым разрешая объявление using, объявление using будет только объявлять имя типа enum в пространство имен (ссылка на стандарт 2003 года - 7.3.3 / 2).
namespace Sample
{
enum Colour { RED,BLUE,GREEN};
}
using Sample::Colour;
using Sample::BLUE;
void foo ()
{
int j = BLUE; // OK
int i = RED; // ERROR
}
Зависимые базовые типы
Чтобы разрешить частичные и явные специализации, когда компилятор анализирует шаблон класса, он не выполняет никаких поисков в зависимых базовых классах. В результате следующий вариант с примером в качестве шаблона не компилируется:
template <typename T>
class Sample
{
public:
enum Colour { RED,BLUE,GREEN};
};
template <typename T>
class Derived : public Sample<T>
{
public:
using Sample<T>::Colour; // What kind of entity is Colour?
Colour foo () // Not OK!
{
return this->RED;
}
};
Проблема в том, что Derived::Colour
обрабатывается компилятором как объект (14.6 / 2):
Предполагается, что имя, используемое в объявлении или определении шаблона и зависящее от параметра-шаблона, не называет тип, если только применимый поиск имени не найдет имя типа или имя не будет определено ключевым словом typename.
Рассматривая два условия, чтобы имя было типом:
- Поиск для
Colour
не находит тип, поскольку не выполняется поиск в зависимой базе Sample<T>
.
- Имя не уточняется
typename
Поэтому в примере необходимо ключевое слово typename
:
template <typename T>
class Derived : public Sample<T>
{
public:
using typename Sample<T>::Colour; // Colour is treated as a typedef-name
Colour foo () // OK
{
return this->RED;
}
};
Примечание: Версия стандарта '98 не позволяла использовать typename
с объявлением об использовании, поэтому вышеприведенное исправление было невозможно. См. Доступ к типам из зависимых базовых классов и CWG11 .