Подтвердить что ты не робот

Специализация класса шаблона как структуры

Я только что специализировался на std::hash для пользовательского типа, используя:

template<>
struct hash<...> {...};

Когда VC10 приветствовал меня предупреждением:

warning C4099: 'std:: hash < _Kty > ': имя типа, впервые увиденное с использованием 'class' теперь видно, используя 'struct'

и я узнал, что его стандартная библиотека объявляет std::hash как class, тогда как в стандарте (или в последнем свободном черновом ящике) объявляется его как struct.

Ну, конечно, я знаю, что структура не отличается от класса (за исключением разных типов доступа по умолчанию и типов наследования). Но мои вопросы:

  • Нарушает ли стандарт VC10 стандарт или не может обменять struct на class на любые стандартные компоненты библиотеки (если, конечно, требуемые типы доступа для членов остаются неизменными)?
  • Является ли законным специализировать класс шаблона как структуру и наоборот, или это создает проблемы с разрешением имен и т.п. (по крайней мере, VC10 считает, что стоит предупредить).
4b9b3361

Ответ 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: Не волнуйтесь, это не должно приводить к каким-либо странным поведением. Просто будьте осторожны с областями функций, которые вы определяете. Что касается предупреждения, он фактически довольно общий (т.е. Специально не для шаблонов), поэтому мне было бы безразлично.

Изменить: см. также ответ на этот вопрос, который в основном говорит о том, что он не имеет никакого значения в стандарте, но некоторые компиляторы могут вести себя странно.