Подтвердить что ты не робот

Все ли реализовано в С++ 11 STL?

Я знаю, что libs, такие как <map>, <vector> и <algorithm>, могут быть реализованы пользователем, даже если они не существуют в стандартных библиотеках.

Но есть ли некоторые из классов или функций в С++ 11 STL только "компилятор-магия", которые невозможно выполнить вручную?


ИЗМЕНИТЬ По STL я имел в виду стандартные библиотеки шаблонов, которые не требуют дополнительной привязки.

4b9b3361

Ответ 1

Если вы имеете в виду часть стандартной библиотеки, созданной из стандартной библиотеки шаблонов Александра Степанова, то вы можете реализовать ее все без каких-либо компиляторов "магии" (т.е. вам нужна только нормальная функциональность, требуемая остальной частью С++ стандарт).

Алгоритмы работают на итераторах. Операции, которые им нужны из итератора, определяются классом итератора, на котором они работают (см. Ниже). Алгоритм просто выполняет обычные операции, такие как назначение элементам и замена элементов.

Все итераторы предоставляют несколько операций, таких как приращение и разыменование. Двунаправленные итераторы также обеспечивают декремент, а итераторы произвольного доступа обеспечивают сложение/вычитание. Ни один из них не является особенно сложным, он реализуется с использованием стандартных функций компилятора.

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

Если вы берете "STL" для обозначения библиотеки STandard в целом, то да, есть немало частей, для которых требуется магия компилятора разных типов.

Некоторые из них определены в терминах компонентов более низкого уровня, поэтому (например) iostreams определены в терминах C getchar/puthchar 1 для получения данных из/во внешний мир. Другие части (например, черты типа, std:: uncaught_exception) обеспечивают интерфейс для данных, сгенерированных компилятором, но недоступными для переносимого кода другими способами.


1. Обратите внимание, однако, что хотя iostreams определены с точки зрения чтения и записи через C-функции, им не требуется фактически использовать эти C-функции, чтобы делать то же самое, что и они.

Ответ 2

Я предполагаю, что вы имеете в виду стандартную библиотеку С++ 11, а не STL (которая является библиотекой алгоритмов, итераторов и контейнеров с 1990-х годов).

Ответ зависит от того, что вы подразумеваете под "реализованным вручную". Вы имеете в виду в чистом С++? то есть нет кода сборки и каких-либо специфичных для ОС функций, таких как функции распределения памяти POSIX или даже системные вызовы нижнего уровня для ядра?

Потому что, если вы готовы писать сборку и вызывать прямо в ядро, вы можете реализовать почти все, но это не очень практично. Даже писать собственные std::malloc() или operator new очень сложно, не строя его поверх чего-то более низкого уровня, например sbrk(). Без чего-то вроде malloc трудно писать std::allocator и так сложно реализовать std::vector!

std::system_clock также полагается на средства, предоставляемые операционной системой, вам либо нужен API более низкого уровня, такой как POSIX clock_gettime(), либо доступ к аппаратным часам в CPU. Даже std::time(), определенный в <ctime>, нуждается в этом.

Итак, предположим, что полагаться на библиотеку C для таких функций, как malloc, это нормально, но мы хотим избежать написания сборки и не-С++.

Невозможно эффективно реализовать std::atomic в чистом С++. Для обеспечения необходимых гарантий синхронизации вам понадобится магия компилятора или код сборки. Реализация libstdС++ std::atomic опирается на GCC __ атомные встроенные функции, которые являются "масками компилятора". В реализации libС++ std::atomic используется ключевое слово _Atomic, которое определено C11 и поддерживается clang++, но не определено в стандартном С++. В обоих случаях реализация библиотеки основывается на нестандартных функциях компилятора, чтобы предоставить сборку для конкретной платформы, необходимую для обеспечения требуемого поведения.

В качестве альтернативы вы можете просто реализовать std::atomic неэффективно с помощью мьютекса, но это просто сдвигает требование "магических" свойств синхронизации к типу мьютекса. По крайней мере, реализация должна обеспечить std::atomic_flag, которая не может быть выполнена в чистом С++. Без std::atomic_flag другие атомные типы и std::mutex не могут быть реализованы в чистом С++, поэтому требуется либо код сборки для конкретной платформы, либо требуется использовать библиотеку более низкого уровня, такую ​​как Pthreads, которая предоставляет необходимые примитивы (которые сами либо будут реализованный в сборе или с непортативной маской компилятора).

Как указано в Как std:: async "store" произвольное исключение? существуют части среды выполнения С++, такие как std::typeinfo и std::exception_ptr, которые могут быть написаны на С++, но не переносимы. Время выполнения должно определять структуры данных и внутренние данные RTTI и обработку исключений и предоставлять точки входа, которые компилятор вызовет так, например, throw в коде С++ вызывает соответствующую процедуру из среды выполнения для выделения объекта исключения. Таким образом, вы можете реализовать эти вещи самостоятельно, но если вы не соответствуете правильному API, компилятор не будет их использовать, чтобы они не работали!

Но даже если вы готовы писать сборку и вызывать прямо в ядро, некоторые черты типа полагаются на магию компилятора и не могут быть реализованы пользователем, например is_standard_layout, is_trivial, is_trivially_constructible и другие черты is_trivially_xxx. Все они зависят от свойств типа, которые не могут быть проверены в коде, только компилятор может провести необходимую проверку и сказать вам, имеет ли тип свойство (и то же самое относится к признаку С++ 14 is_final).

Ответ 3

Не все из них доступны для пользователя. Некоторые классы могут быть реализованы только с расширениями компилятора.

GCC предоставляет "компилятор-магия" для типов типов.

GCC также предоставляет атомные встроенные функции,

initializer_list обычно реализуется на том, что сам компилятор имеет доступ к частной функции, которая в этом случае является конструктором.

Ответ 4

Оператор typeid, который зависит от <typeinfo> является одним из примеров.

Другим случаем является initializer_list, который в основном является библиотека с особыми привилегиями на базовом языке. Это, например, рассматривается в правилах инициализации переменных.

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