Меня недавно укусила (упрощенно)
struct Base {
typedef char T;
};
template<typename T>
struct Foo : Base {
T x[50]; // This is Base::T, not the template parameter
};
Другими словами, имя члена класса скрывает параметр шаблона (даже если он исходит из базового класса, поэтому не является полностью очевидным в локальном контексте).
Проведя некоторый эксперимент, я обнаружил, что:
struct Base {
typedef char T;
};
template<typename T, typename B>
struct Foo : B {
T x[50]; // This T is the template parameter,
// even passing Base as B
};
Единственный выход, о котором я могу подумать, это дать некрасивые имена параметров шаблона, а также означает, что невозможно безопасно написать шаблон без использования зарезервированных имен (поскольку класс, используемый в шаблоне, может конфликтовать с именами параметров … обратите внимание, что много C ++ код использует неприглядные имена для частных пользователей).
PS: я не копался в стандарте по этому вопросу, но и g ++, и clang ++ согласны с таким поведением, поэтому я не думаю, что это ошибка.
PPS: в реальном коде скрытый параметр шаблона был назван tid
и был целым числом, а не типом. -Wall
этого было недостаточно, чтобы сообщить о сокрытии, и я обнаружил его после пары часов отладки с помощью valgrind.
Это правило (указано в [Temp.local] / 9) является предметом открытой языковой проблемы, созданной более 11 лет назад — основная проблема № 459. CWG тщательно это обсудила. О намерении Майк Миллер упоминает, что
Обоснование текущей спецификации действительно очень просто:
«Если не объявлено повторно в производном классе, члены базового класса также считаются членами производного класса». (10
[class.derived] пункт 2)В рамках класса члены скрывают не членов.
Вот и все. Поскольку параметры шаблона не являются членами, они
скрыты по именам членов (наследуются или нет). Я не нахожу это
«Странно» или даже особенно удивительно.
Обоснование:
У нас есть некоторое сочувствие к изменению, но текущие правила прямо не соответствуют правилам поиска, поэтому они не являются «неправильными». Создание невидимых частных пользователей также решило бы эту проблему. Мы были бы готовы взглянуть на статью, предлагающую это. [..]CWG решила не рассматривать вопрос об изменении существующих правил в настоящее время без более детального изучения вопроса.
К сожалению, такая статья еще не была написана, и поэтому правило сохраняется до сегодняшнего дня.