cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

Убрать зависимость core language features от заголовков <initializer_list> и <compare> #456

Open oficsu opened 3 years ago

oficsu commented 3 years ago

На текущий момент есть места, где чисто-языковые возможности зависят от типов, объявленных в заголовках стандартной библиотеки. Следующие примеры являются невалидным 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

AndreyG commented 3 years ago

Я думаю, в 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 потребуется добавлять встроенный шаблон, такого прецедента еще не было.