Почему std:: is_base_of <T, T> true, когда T является типом класса, но false, когда T является встроенным типом?

Per [meta.rel] (20.10.6 в С++ 14), для типа класса T, std::is_base_of<T,T> - true, но для встроенного типа T, std::is_base_of<T,T> - false, Говоря по-разному, типы классов являются основами самих себя, но встроенных типов нет. Какова мотивация/полезность этой разницы в лечении?

Ответ 1

Обоснование вернулось довольно далеко, и оно плохо документировано.

is_base_of изначально назывался is_base_and_derived и был введен в TR1. Дейв Абрахамс представил проблему против этого класса в N1541, номер 3.13:

В настоящее время is_base_and_derived<X,Y> возвращает false, когда X и Yодинаковы. Это технически правильно (X не является собственной базой класс), но это не полезно. Определение следует ослабить return true, когда X и Y совпадают, даже если тип isnt фактически класс.

К сожалению, проблема не объясняет, почему это определение не полезно. Однако точка зрения не была уникальной в то время (2003). Andrei Alexandrescu Modern С++ Design, опубликованный двумя годами ранее, имел одинаковую черту и почти тот же комментарий в разделе 2.7 о его макросе SUPERSUBCLASS, хотя в этой книге также добавлено обходной макрос, если вы действительно не хотите, чтобы класс считался его собственной базой.

Современный дизайн С++ продолжает использовать SUPERSUBCLASS в разделе 3.12, чтобы заказать Typelist в порядке наследования. Глубоко в деталях этого упражнения, тот факт, что SUPERSUBCLASS(T, T) является истинным, используется (для удобства реализации).

К 2004 году отчет TR1, N1647, принял понятие о том, что std::is_base_of<T,T>::value == true был полезен, когда T является классом типа non-union.

N2255 дополнительно разъясняет, как is_base_of должен работать для неклассических типов, и это изменение привело к формулировке, которую вы видите сегодня. Однако существуют обширные редакционные различия между тем, что предлагает эта принятая статья, и тем, что было создано в следующем проекте (N2284). Мое мнение таково, что редактор значительно улучшил формулировку.

Недокументированное обоснование того, почему N2255 создало разделение между типами неединичных классов и всего остального, состоит в том, что is_base_of исторически ответил на вопросы о иерархии наследования типы, с только удобным "трюком", что класс можно считать собственной базой через анализ "is-a". Однако типы, которые не могут участвовать в отношениях наследования, никогда не должны квалифицироваться как базовые классы, согласно многочисленным авторам этого признака.

Был ли это лучший дизайн для обсуждения. Однако есть достаточные черты (например, is_class и is_same), чтобы создавать все, что вам нужно, из этих основных черт.

Это скорее история, а не просто "почему". Однако точка этого ответа состоит в том, чтобы вызывать, что is_base_of развивалось в течение большого количества времени, через многие итерации. И каждая итерация ощущалась в то время как эволюционное улучшение того, что было раньше.

И все это сводится к: Это спецификация, которую комитет считал наиболее полезной. Но поскольку спецификация и дизайн развивались на протяжении многих лет, и через нескольких авторов, нет хорошего общего дизайнерского документа или обоснования.

Ответ 2

Встроенные типы не являются классами, а вещи, которые не являются классами, не могут быть основой чего-либо.

Если что-то меня несколько удивляет тем, что std::is_base_of<T,T> истинно даже для типов классов, но это, вероятно, отношение "можно рассматривать как" для классов.

Мех, я не знаю.