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




class struct template-specialization (3)

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

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

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

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

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

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

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

Answers

Для 1: я не уверен, но я считаю, что это ошибка.

Для 2: не волнуйтесь, это не должно приводить к какому-либо странному поведению. Просто будьте осторожны с областями функций, которые вы определяете. Что касается предупреждения, оно на самом деле довольно общее (то есть не специально для шаблонов), поэтому мне было бы все равно.

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


Прежде всего, вот ответ на 2. взят из 14.5.1 [temp.class] параграф 4:

При переобъявлении, частичной специализации, явной специализации или явной реализации шаблона класса ключ класса должен согласовываться в натуральной форме с исходным объявлением шаблона класса.

Однако struct и class ссылаются на один и тот же ключ класса в соответствии с 7.1.6.3 [dcl.type.elab] абзаца 3 последнего предложения:

Ключевое слово class-key или enum, присутствующее в подробном спецификаторе типа, должно в натуре согласовываться с объявлением, на которое ссылается имя в подробном спецификаторе типа. [...] Таким образом, в любом разработанном спецификаторе типа ключевое слово enum должно использоваться для ссылки на перечисление, ключ класса объединения должен использоваться для ссылки на объединение, а также ключ класса или структуры class-key должен использоваться для ссылки на класс, объявленный с использованием class или struct class-key.

Попытки g ++, clang и EDG согласны с тем, что можно специализировать шаблон, объявленный как struct как class . Тем не менее, Clang предупреждает об изменении от struct к class или наоборот. Исходя из этого, стандартная библиотека может свободно выбирать любое ключевое слово, которое она считает подходящим для определения. Очевидно, что если компилятор отклоняет код в результате, что-то серьезно нарушается, но я думаю, что в данном случае это не библиотека, а компилятор.


Особо следует отметить свойства статических свойств и экземпляров, показанные в следующем примере:

class my_cls:
  my_prop = 0

#static property
print my_cls.my_prop  #--> 0

#assign value to static property
my_cls.my_prop = 1 
print my_cls.my_prop  #--> 1

#access static property thru' instance
my_inst = my_cls()
print my_inst.my_prop #--> 1

#instance property is different from static property 
#after being assigned a value
my_inst.my_prop = 2
print my_cls.my_prop  #--> 1
print my_inst.my_prop #--> 2

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







c++ class struct template-specialization