Убрать зависимость core language features от заголовков <initializer_list> и <compare>
На текущий момент есть места, где чисто-языковые возможности зависят от типов, объявленных в заголовках стандартной библиотеки. Следующие примеры являются невалидным C++:
auto x = {0, 42};
using initializer_list = decltype(x);
using strong_ordering = decltype(0 <=> 42);
На практике, не включив заголовки <initializer_list> и <compare> мы не имеем права сделать такие базовые вещи, как:
a) инициализировать переменную;
b) сравнить два числа
Вывод типов через выражение
Однако, на деле, у нас допустим похожий механизм — мы имеем право вывести size_t через языковые конструкции, чем, например, пользуется компилятор:
using size_t = decltype(sizeof 0);
Аналогичным образом мы могли бы определить std::initializer_list и std::strong_ordering:
auto x = {0, 42};
using initializer_list = decltype(x);
using strong_ordering = decltype(0 <=> 42);
Сейчас это ошибка компиляции. Если посмотреть на вывод трёх компиляторв, каждый из них понимает, где здесь ошибка и прямым текстом требует подключить нужные заголовоки. Но если им достоверно известно, какой заголовок подключать — очень большой вопрос, зачем этот заголовок, собственно, нужен, тем более, почему он нужен для определения типа, использующегося в языковой фиче
Кроме того, если позволить такую реализацию, вопрос <compare> всё ещё остаётся нерешённым в полной мере, поскольку там определяются также std::weak_ordering и std::partial_ordering
Ключевые слова-типы
Как более надёжная альтернатива (пусть, и менее эстетичная) — пойти по стопам комитета стандартизации C и добавить встроенные языковые типы, например _Initializer_list, _Strong_ordering, _Weak_ordering, _Partial_ordering, а в std:: сделать на них лишь алиасы
Почему это плохо? Во-первых, такая зависимость не вяжется с желанием иметь отчуждаемую стандартную библиотеку. Во-вторых, буду честен, в первую очередь это крайне уродливая зависимость с эстетической точки зрения. Из реальных практических примеров проблемы — встречались случаи обхода другими программистами этой проблемы в случаях, когда имелся компилятор свежей версии, а библиотеки под него нет — в этом случае ничего не остаётся, кроме как написать недостающую типы в пространстве имён std::, что формально является неопределённым поведением
Я думаю, в C++ есть и другие примеры зависимости языка от собственной стандартной библиотеки, которые также стоит исправить, если будут найдены
Без заглядывания в стандарт, я склонен считать, что проблема здесь две. Самая незначительная из них — вординг стандарта, но вторая серьёзнее — ABI. Как дальше манглить условный _Initializer_list? Всё ещё как std::initializer_list? Однако, если кто-то сможет найти другие проблемы — буду рад комментариям
Ссылки на сообщения топика, изначально натолкнувшего на эту идею: #1, #2, #3, #4, #5, #6, #7
Я думаю, в C++ есть и другие примеры зависимости языка от собственной стандартной библиотеки, которые также стоит исправить, если будут найдены
type_info, nullptr_t. Собственно, type_info был первым классом, использующимся в core language, и в тот момент (C++98), когда для его использования решили требовать #include <typeinfo> выбор был сделан.
using initializer_list = decltype(x); using strong_ordering = decltype(0 <=> 42);
Так сделано для std::nullptr_t, но для type_info, initializer_list и strong_ordering, если идти по этому пути, то придется зашивать в компилятор определения этих классов, при этом, заметим, что к initializer_list-у в C++14 и С++17 добавляли новые члены. Сейчас в компилятор встроены forward declaration для этих классов (к примеру, type_info: https://gcc.godbolt.org/z/7GWb3cab3), а определения по-честному парсятся из хедеров.
добавить встроенные языковые типы, например
_Initializer_list, ...
В отличии от других builtin типов (short, int, long, ...) для initializer_list потребуется добавлять встроенный шаблон, такого прецедента еще не было.