Специализация класса шаблона как структуры
Я только что специализировался на std::hash
для пользовательского типа, используя:
template<>
struct hash<...> {...};
Когда VC10 приветствовал меня предупреждением:
warning C4099: 'std:: hash < _Kty > ': имя типа, впервые увиденное с использованием 'class' теперь видно, используя 'struct'
и я узнал, что его стандартная библиотека объявляет std::hash
как class
, тогда как в стандарте (или в последнем свободном черновом ящике) объявляется его как struct
.
Ну, конечно, я знаю, что структура не отличается от класса (за исключением разных типов доступа по умолчанию и типов наследования). Но мои вопросы:
- Нарушает ли стандарт VC10 стандарт или не может обменять
struct
на class
на любые стандартные компоненты библиотеки (если, конечно, требуемые типы доступа для членов остаются неизменными)?
- Является ли законным специализировать класс шаблона как структуру и наоборот, или это создает проблемы с разрешением имен и т.п. (по крайней мере, VC10 считает, что стоит предупредить).
Ответы
Ответ 1
Прежде всего, вот ответ на 2. взятый из пункта 14.5.1 [temp.class]:
В повторной декларации, частичной специализации, явной специализации или явном экземпляре шаблона класса ключ класса должен согласовываться с оригинальным объявлением шаблона класса.
Однако struct
и class
ссылаются на один и тот же ключ класса в соответствии с пунктом 7.1.6.3 [dcl.type.elab], приведенным в последнем абзаце 3:
Ключевое слово или ключевое слово enum, присутствующее в спецификаторе разработанного типа, должны согласовываться в натуральной форме с объявлением, к которому относится имя в спецификаторе разработанного типа. [...] Таким образом, в любом специфицированном спецификаторе типа ключевое слово enum должно использоваться для ссылки на перечисление, ключ класса union должен использоваться для ссылки на объединение, а также класс-класс или класс-ключ класса должны использоваться для обозначения класса, объявленного с использованием класса или класса класса.
Попытка g++, clang и EDG согласуется с тем, что можно специализировать шаблон, объявленный как struct
, как class
. Тем не менее, clang предупреждает о том, что он изменился с struct
на class
или наоборот. Исходя из этого, стандартная библиотека может выбирать любое ключевое слово, которое оно считает подходящим для определения. Очевидно, что если компилятор отвергает код, в результате что что-то серьезно нарушается, но я думаю, что в этом случае это скорее компилятор, чем библиотека, которая имеет ошибку.
Ответ 2
Для 1: я не уверен, но я считаю, что это ошибка.
Для 2: Не волнуйтесь, это не должно приводить к каким-либо странным поведением. Просто будьте осторожны с областями функций, которые вы определяете. Что касается предупреждения, он фактически довольно общий (т.е. Специально не для шаблонов), поэтому мне было бы безразлично.
Изменить: см. также ответ на этот вопрос, который в основном говорит о том, что он не имеет никакого значения в стандарте, но некоторые компиляторы могут вести себя странно.