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