标准库是否需要符合标准?
标准库是否要求符合标准?我有一种感觉,标准库不符合标准。这种感觉的基础是编译器生成的错误消息。例如,有时 GCC 会给出以前缀 __gxx 开头的错误消息以及许多其他我现在不记得的错误消息。但看到它们让我感觉这些是编译器特定的消息,不同的编译器将无法编译 GCC 提供的标准库,反之亦然。这是真的吗?
换句话说,这个问题可以问为:
- 一个编译器提供的标准库可以用其他编译器编译吗?
- 当我们说某个特定的编译器符合标准时,是否自动意味着它附带的 stdlib 也符合标准?或者它仅仅意味着这个编译器可以编译我们程序员编写的符合标准的代码?
- 我可以在使用不同编译器来编译项目的项目中使用一个编译器提供的标准库吗?可移植性与标准一致性相同吗?
这些问题是从不同的角度来看待同一个大问题。因此,请帮助我理解当我们说编译器 X 符合标准时到底意味着什么。
Are standard library required to be standard conformant? I've this feeling that standard library aren't standard conformant. The basis of this feeling is the error messages generated by the compiler(s). For example, sometime GCC gives error messages which starts with prefix __gxx
and many others which I don't remember as of now. But seeing them gives me feeling that these are very compiler specific messages, and different compilers wouldn't be able to compile standard library provided by GCC, and vice-versa. Is it true?
The question can be asked in other words as:
- Can standard library provided by one compiler be compiled with other compilers?
- When we say a particular compiler is standard conformant, does it automatically mean that the stdlib which comes with it is also standard-conformant? Or it simply means that this compiler can compile standard-conformant code written by us, programmers?
- Can I use standard library provided by one compiler, in my project which uses a different compiler to compile the project? Is portability same as standard-conformance?
These questions are different angles to look at the same big question. So, please help me understanding what does it exactly mean when we say compiler X is standard-conformant.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
标准库是实现的细节。它甚至可能不会被“编译”,因为标准不要求它由“文件”[标头]组成:
该标准仔细地放宽了对实现的要求,以便该库可以“内置”到编译器中(也称为内在函数)。例如,扩展 std 命名空间或 #defining 标准库中使用的名称会给您带来未定义的行为。
The standard library is a detail of implementation. It may not even be 'compiled' in the sense that the standard doesn't require it to consist of 'files' [headers]:
The standard carefully eases the requirements on the implementation, so that the library may be 'built-in' to the compiler (a.k.a intrinsics). For example, extending the
std
namespace, or #defining a name used in the standard library gives you undefined behavior.是的,标准库必须遵守标准,但其中有很大的灵活性。标准不要求特定的功能实现,并且实现可以自由添加内部功能、属性……只要满足要求。
请注意,符合标准的库和仅使用标准功能实现的库是不同的概念。
关于以下具体问题:
有些会,有些不会。标准库的实现可以使用编译器内在函数来执行某些操作,这些功能仅在一个平台中存在,而在其他平台中不存在......不过,一些STL实现可以使用不同的编译器进行编译,例如STLPort、Dinkumware(这也是 VS 中附带的,经过一些 VS 修改)
这意味着库必须一致,但同样,标准并不强制库的实现,并且这些库可以使用非标准扩展等,这将在一个编译器中工作,但可能无法在其他编译器中工作。例如,考虑一下shared_ptr的实现,引用计数必须以原子方式更新,但当前标准中没有对整数的原子操作,因此必须以非标准方式实现特征。
未必。
Yes, standard libraries must adhere to the standard, but there is quite a bit of flexibility in that. The standard does not require a particular implementation of the functions, and the implementation is free to add internal functions, attributes... as long as the requirements are met.
Note that there is a different concept of the library conforming with the standard and the library being implemented using only standard features.
On the particular questions below:
Some will, some won't. The implementation of the standard library can use compiler intrinsics for some operations, of features present only in one platform and not others... Some STL implementations can be compiled with different compilers though, like STLPort, Dinkumware (which is also the one shipped in VS, with some VS modifications)
It means that the library must be conformant, but again, the standard does not mandate the implementation of the library, and these can use non-standard extensions and the like, which will work in one compiler but possibly not in other compilers. Consider, for example, an implementation of
shared_ptr
, the reference count has to be updated atomically but there was no atomic operations on integers in the current standard, so it has to be implemented in terms of non-standard features.Not necessarily.
根据定义,实现必须符合标准才能符合标准,是的。
否则它不是 C++ 标准库的实现,而是其他东西的实现。
这取决于措辞,不是吗?如果工具链声称包含标准库的实现,人们可以合理地假设它是兼容的。编译器可执行文件本身兼容并不是一回事,除非库实现内置于编译器可执行文件中。
但这只是文字游戏。
当然不是。两个一致的实现可能彼此完全不兼容。
没关系。工具链可以实现库,但是它选择,只要接口符合标准。该标准并没有规定实现不能在其工作中使用符号
__gxx
。顺便说一句
,尽管如此,它确实说,在某些情况下,程序员可能不会使用带前导下划线的符号!
您不允许 (
[lib.requirements]
/[requirements]
) 使用以下任何名称:另外,在 C++0x 中,保留不以下划线开头的文字后缀。
By definition, an implementation must conform to the standard to be standard-conformant, yes.
Otherwise it's not an implementation of the C++ Standard Library, but of some other thing.
This would depend on the wording, wouldn't it? If the toolchain purports to include an implementation of the Standard Library, one may reasonably assume that it's compliant. That the compiler executable itself is compliant is not the same thing, unless the library implementation is built into the compiler executable.
But this is all just wordplay.
Of course not. Two conformant implementations may be completely incompatible with each other.
That's fine. The toolchain may implement the library however it chooses, as long as the interface conforms to the standard. The standard does not say that the implementation cannot use a symbol
__gxx
in its work.BTW
Though, it does say that the programmer may not use symbols with leading underscores, in some cases!
You aren't allowed (
[lib.requirements]
/[requirements]
) to use any name which:Also, in C++0x, literal suffixes that do not start with an underscore are reserved.
库面向用户的API应该是标准的;然而,实施并不是必须的。您将看到一个这样的示例,其中函数的标准版本被优化的变体替换(具有不同的名称,因为有时替换仅在某些情况下才可能,例如当可以证明适当的对齐时)。这也意味着一个编译器的标准库的实现可能无法由不同的编译器构建(这可能会导致移植时出现引导问题,但这是另一个问题)。
The user-facing API of the library should be standard; the implementation is not required to be, however. You're seeing an example of this, where the standard version of a function is replaced with an optimized variant (with a different name because sometimes the replacement is only possible in some circumstances, such as when appropriate alignment can be proven). This also means that the implementation of one compiler's standard library might not be buildable by a different compiler (which can lead to bootstrapping issues when porting, but that's another issue).
这意味着编译器为标准库提供了标准提出的所有要求,并且实现本身符合标准中的所有要求。问题是,除了通用接口之外,标准库的“要求”相当自由。
It means that the compiler provides the standard library with all the requirements layed upon by the standard and that the implementation itself conformes to all requirements in the standard. The thing is, the "requirements" for the standard library are quite liberal after the general interface.
标准库只需满足最低限度的接口。在它的实现中,它可以做任何它想做的事情,因为,好吧,这就是实现,尽管我很确定存在一些标识符限制等以防止冲突。
标准库实现不必以任何方式进行移植。它们可以,但远非必然。
The Standard library only has to meet a minimum interface. In it's implementation it can do whatever it wants, because, well, it's the implementation, although I'm pretty sure there are some identifier restrictions and such to prevent clashes.
The Standard library implementation does not have to be portable in any way. They can be, but far from necessarily.
该标准对标准库的接口进行了限制,而不是对其实现进行了限制。它不遗余力地表明标准库头可以做用户代码不能做的事情...例如,
__MACRO__NAME__
是为实现保留的。显然,只有实现才能真正将所有这些函数和类型放入命名空间 std 中。大多数情况下,可以编写“可移植”实现。但它的性能可能会较差...作为一个简单的示例,请考虑
offsetof
宏的传统实现。它通常涉及取消引用空指针,这在形式上是未定义的行为,但因为实现知道其平台如何工作,所以没关系。可移植版本无法做到这一点,因此它必须实际创建所提供类型的新实例以保持一切正常运行。C++0x 中的相当多的类型特征可能需要编译器支持,这使得“可移植”实现变得困难甚至不可能。例如,没有标准方法可以分析任意类型是否是 POD,这就是为什么
boost::is_pod
需要通过某些平台上的专门化来提供用户支持。还需要考虑到许多标准库并不是仅限头文件。其他位可以用完全不同的语言编写......只要它们全部正确链接在一起,就没有关系。如果运行时是用 Lisp 实现的,显然它不会是可以可靠地放入不同编译器工具链的 C++ 兼容代码。
The standard places restrictions on the interface of the standard library, not the implementation. It goes out of its way to make it clear that standard library headers can do things user code can not...
__MACRO__NAME__
is reserved for the implementation, for instance. And obviously, only the implementation can actually put all these functions and types into namespace std.Mostly, a "portable" implementation could be written. But it would likely be less performant... as an easy example, consider the traditional implementation of the
offsetof
macro. It generally involves dereferencing a null pointer, which is formally undefined behavior, but because the implementation knows how its platform works, that's okay. A portable version can not do this, so it would have to actually create a new instance of the provided type to keep everything on the up and up.Quite a few type traits in C++0x likely require compiler support, which makes a "portable" implementation somewhere between difficult and impossible. There's no standard way to analyze if an arbitrary type is POD, for instance, which is why
boost::is_pod
requires user support via specialization on some platforms.There is also the consideration that a lot of the standard library is not header-only. The other bits can be written in a completely different language... so long as it all links together properly, it doesn't matter. If the runtime is implemented in Lisp, obviously it won't be C++ compliant code that can be reliably dropped into a different compiler toolchain.
假设该库符合标准,是的(我知道这是一种先有鸡还是先有蛋的问题)。
是的,尽管我不知道有任何完全确认的编译器。请注意,作为程序员,我们遵循的标准与标准库不同。例如,允许实现使用包含
__
(双下划线)的标识符。您应该能够编译并使用这样的库。您几乎肯定无法使用任何已编译的库文件(静态或动态)文件,因为名称修饰会有所不同。
Assuming that the library is standards conforming, yes (I know this is kind of chicken-and-egg).
Yes, although I'm not aware of any fully confirming compiler. Note that standards conforming for us as programmers is different from the standard library. For example the implementation is allowed to use identifiers containing
__
(double underscore).You should be able to compile and use such a library. You almost certainly wouldn't be able to use any compiled library files (static or dynamic) file because name mangling would be different.