Доступ к типам из зависимых базовых классов
-
21-08-2019 - |
Вопрос
Кто-нибудь знает, почему объявления использования не работают для импорта имен типов из зависимых базовых классов?Они работают для переменных-членов и функций, но, по крайней мере, в GCC 4.3, они игнорируются для типов.
template <class T>
struct Base
{
typedef T value_type;
};
template <class T>
struct Derived : Base<T>
{
// Version 1: error on conforming compilers
value_type get();
// Version 2: OK, but unwieldy for repeated references
typename Base<T>::value_type get();
// Version 3: OK, but unwieldy for many types or deep inheritance
typedef typename Base<T>::value_type value_type;
value_type get();
// Version 4: why doesn't this work?
using typename Base<T>::value_type;
value_type get(); // GCC: `value_type' is not a type
};
У меня есть базовый класс с набором определений типов в стиле распределителя, которые я хотел бы наследовать на нескольких уровнях наследования.Лучшее решение, которое я нашел на данный момент, — это версия 3, указанная выше, но мне любопытно, почему версия 4 не работает.GCC принимает декларацию использования, но, похоже, игнорирует ее.
Я проверил стандарт C++, C++ Prog.Ланг.3-е изд.[Stroustrup] и шаблоны C++ [Vandevourde, Josuttis], но ни в одном из них, похоже, не рассматривается вопрос о том, можно ли применять объявления using к зависимым типам базовых классов.
Если вам поможет другой пример, здесь задают тот же вопрос, но на самом деле не ответил в списке рассылки GCC.Спрашивающий указывает, что он видел «использование имени типа» где-то еще, но GCC, похоже, не поддерживает его.У меня нет другого соответствующего компилятора, чтобы протестировать его.
Решение
Как указывает Ричард Корден, этот вопрос рассматривался в Отчеты о дефектах стандартного базового языка C++ после ратификации стандарта 2003 г.: Как ключевые слова типа/шаблона взаимодействуют с объявлениями использования?
Предлагаемая резолюция (апрель 2003 г., пересмотрено в октябре 2003 г.):
Добавьте новый абзац в нижнюю часть 7.3.3 [namespace.udecl]:
Если в использовании декларации используется тип ключевого слова и определяет зависимое имя (14.7.2 [temp.dep]), имя, введенное с использованием декларации, рассматривается как имя Typedef (7.1.3 [dcl.typedef])) Полем
Этот текст, похоже, не встречается во втором издании стандарта от 15 октября 2003 г.
GCC еще не выполняет эту резолюцию, как поясняется в ошибка 14258:
------- Комментарий № 3 от Giovanni Bajo 2004-02-27 12:47 что это тип, который импортируется через него.Я полагаю, что это работало благодаря неявному расширению имени типа.
Дублировать ошибка 21484 указывает, что «использование имени типа» работает на компиляторах Comeau и Intel.Поскольку MSVC рассматривает все имена как зависимые, эта конструкция не нужна (но разрешена) для этого компилятора.
Зафиксированный в GCC 4.7 от 13 декабря 2011 г.!
Другие советы
Вы не включили спецификатор доступа (public/protected/private) в шаблон Base перед объявлением typedef для Base::value_type.В результате по умолчанию он является закрытым и недоступен в классах, производных от Base.