C++ 11 STL中的所有内容都是用户可实现的吗?

RnM*_*Mss 31 c++ c++11

我知道libs喜欢<map>,<vector>并且<algorithm>即使它们不存在于标准库中也可以由用户实现.

但是C++ 11 STL中的某些类或函数只是"编译器 - 魔法",无法手动实现吗?


编辑 由STL,我的意思是标准模板库,不需要额外的链接.

Jer*_*fin 27

如果您指的是源自Alexander Stepanov的标准模板库标准库的一部分,那么您可以实现所有这些而无需任何编译器"魔术"(即,您只需要其他C++标准所需的常规功能).

算法在迭代器上运行.它们需要来自迭代器的操作由它们操作的迭代器类定义(见下文).该算法简单地执行正常操作,例如分配元素和交换元素.

所有迭代器都提供一些操作,例如递增和解除引用.双向迭代器也提供递减,随机访问迭代器提供加法/减法.使用标准编译器功能实现这些都不是特别复杂.

容器类似于算法,因为它们主要通过迭代器对数据进行操作.它们还使用allocator类来分配内存,在该内存中创建对象,等等.尽管编写一个分配器过去相当复杂(并且需求记录很少)但是C++ 11已经大大简化了任务(并且它从不需要任何非标准的任务).

如果你把"STL"表示一般的标准库,那么是的,有很多部分需要一些编译器魔法的各种类型.

其中一些是根据较低级别的组件定义的,因此(例如)iostream是根据C的getchar/puthchar 1定义的,用于从/向外界获取数据.其他部分(例如,类型特征,std :: uncaught_exception)提供了由编译器生成的数据的接口,但是通过其他方式不可用于可移植代码.


但是请注意,尽管iostream是通过C函数进行读写定义的,但它们并不需要实际使用这些C函数,只是为了做同样的事情.


Jon*_*ely 18

我假设您的意思是C++ 11标准库,而不是STL(它是20世纪90年代的算法,迭代器和容器库).

答案取决于"手动实施"的含义.你的意思是纯C++吗?即没有汇编代码和没有特定于操作系统的功能,如POSIX内存分配功能,甚至是对内核的低级系统调用?

因为如果你准备编写汇编并直接调用内核,你可以实现几乎所有东西,但它不是很实用.即使是写你自己std::malloc()或者operator new是很难不建立它的东西较低级别,如顶部sbrk().没有像malloc这样的东西很难写std::allocator,很难实现std::vector!

std::system_clock还依赖于操作系统提供的工具,您需要较低级别的API(如POSIX)clock_gettime()或访问CPU中的硬件时钟.甚至std::time()定义<ctime>需要类似的东西.

所以让我们假设依赖C库来获得诸如mallocOK 等功能,但我们希望避免编写汇编和非C++.

std::atomic在纯C++中无法有效实现.您需要一些编译器魔术或汇编代码来提供必要的同步保证.libstdc ++实现std::atomic依赖于GCC的__atomic内置函数,它们是"编译器魔术".libc ++实现std::atomic使用了_Atomic关键字,该关键字由C11定义并受clang++标准C++ 支持但未定义.在这两种情况下,库实现都依赖于编译器的非标准功能来提供提供所需行为所必需的特定于平台的程序集.

或者,您可以std::atomic使用互斥锁低效地实现,但这只是将"魔法"同步属性的要求转移到互斥锁类型上.至少,实现需要提供std::atomic_flag在纯C++中无法完成的实现.如果没有std::atomic_flag其他原子类型并且std::mutex无法在纯C++中实现,那么需要使用特定于平台的汇编代码,或者需要使用较低级别的库(如Pthreads)来提供必要的原语(它们本身将以汇编或非汇编的方式实现) - 便携式编译器魔术).

正如std :: async如何"存储"任意异常所指出的那样存在诸如C++运行时的部分std::typeinfostd::exception_ptr可以用C++编写,但不是可移植.运行时必须定义RTTI和异常处理的数据结构和内部细节,并提供编译器将调用的入口点,以便例如throw在C++代码中从运行时调用相关例程来分配异常对象.所以你可以自己实现这些东西,但除非你遵守正确的API,否则编译器将不会使用它们,因此它们将无法工作!

但是,即使你准备编写汇编并直接调用到内核中,有几个类型的特征依靠编译器魔术和不能由用户来实现,例如is_standard_layout,is_trivial,is_trivially_constructible和其他is_trivially_xxx特性.这些都依赖于无法在代码中测试的类型的属性,只有编译器可以进行必要的检查并告诉您类型是否具有属性(并且同样适用于C++ 14 is_final特征).


Inb*_*ong 11

并非所有这些都是用户可实现的.某些类只能使用编译器扩展来实现.

GCC为类型特征提供"编译器魔术".

GCC还提供原子内置,

initializer_list 通常在该编译器本身可以访问私有函数(在本例中为构造函数)上实现.