C++0x 标准中 export 关键字的最佳解释是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/279404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best explanation for the export keyword in the C++0x standard?
提问by zerbp
I know that in the original C++0x standard there was a feature called export
.
我知道在最初的 C++0x 标准中有一个名为export
.
But I can't find a description or explanation of this feature. What is it supposed to do? Also: which compiler is supporting it?
但我找不到此功能的描述或解释。它应该做什么?另外:哪个编译器支持它?
回答by
Although Standard C++ has no such requirement, some compilers require that all function templates need to be made available in every translation unit that it is used in. In effect, for those compilers, the bodies of template functions must be made available in a header file. To repeat: that means those compilers won't allow them to be defined in non-header files such as .cpp files. To clarify, in C++ese this means that this:
尽管标准 C++ 没有这样的要求,但一些编译器要求所有函数模板都需要在使用它的每个翻译单元中可用。 实际上,对于这些编译器,模板函数的主体必须在头文件中可用. 再说一遍:这意味着这些编译器不允许在非头文件(如 .cpp 文件)中定义它们。澄清一下,在 C++ese 中,这意味着:
// ORIGINAL version of xyz.h
template <typename T>
struct xyz
{
xyz();
~xyz();
};
would NOT be satisfied with these definitions of the ctor and dtors:
不会对 ctor 和 dtors 的这些定义感到满意:
// ORIGINAL version of xyz.cpp
#include "xyz.h"
template <typename T>
xyz<T>::xyz() {}
template <typename T>
xyz<T>::~xyz() {}
because using it:
因为使用它:
// main.cpp
#include "xyz.h"
int main()
{
xyz<int> xyzint;
return 0;
}
will produce an error. For instance, with Comeau C++ you'd get:
会产生错误。例如,使用 Comeau C++,您将获得:
C:\export>como xyz.cpp main.cpp C++'ing xyz.cpp... Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86 Copyright 1988-2004 Comeau Computing. All rights reserved. MODE:non-strict warnings microsoft C++ C++'ing main.cpp... Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86 Copyright 1988-2004 Comeau Computing. All rights reserved. MODE:non-strict warnings microsoft C++ main.obj : error LNK2001: unresolved external symbol xyz<T1>::~xyz<int>() [with T1=int] main.obj : error LNK2019: unresolved external symbol xyz<T1>::xyz<int>() [with T1=int] referenced in function _main aout.exe : fatal error LNK1120: 2 unresolved externals
C:\export>como xyz.cpp main.cpp C++'ing xyz.cpp... Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86 Copyright 1988-2004 Comeau Computing. All rights reserved. MODE:non-strict warnings microsoft C++ C++'ing main.cpp... Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86 Copyright 1988-2004 Comeau Computing. All rights reserved. MODE:non-strict warnings microsoft C++ main.obj : error LNK2001: unresolved external symbol xyz<T1>::~xyz<int>() [with T1=int] main.obj : error LNK2019: unresolved external symbol xyz<T1>::xyz<int>() [with T1=int] referenced in function _main aout.exe : fatal error LNK1120: 2 unresolved externals
because there is no use of the ctor or dtor within xyz.cpp, therefore, there is no instantiations that needs to occur from there. For better or worse, this is how templates work.
因为在 xyz.cpp 中没有使用 ctor 或 dtor,因此,不需要从那里进行实例化。无论好坏,这就是模板的工作方式。
One way around this is to explicitly request the instantiation of xyz
, in this example of xyz<int>
. In a brute force effort, this could be added to xyz.cpp by adding this line at the end of it:
解决此问题的一种方法是xyz
在此示例中显式请求 的实例化xyz<int>
。在蛮力的努力中,可以通过在其末尾添加以下行将其添加到 xyz.cpp 中:
template xyz<int>;
which requests that (all of) xyz<int>
be instantiated. That's kind of in the wrong place though, since it means that everytime a new xyz type is brought about that the implementation file xyz.cpp must be modified. A less intrusive way to avoid that file is to create another:
它要求(全部)xyz<int>
被实例化。不过这有点不对劲,因为这意味着每次出现新的 xyz 类型时,都必须修改实现文件 xyz.cpp。避免该文件的侵入性较小的方法是创建另一个:
// xyztir.cpp
#include "xyz.cpp" // .cpp file!!!, not .h file!!
template xyz<int>;
This is still somewhat painful because it still requires a manual intervention everytime a new xyz is brought forth. In a non-trivial program this could be an unreasonable maintenance demand.
这仍然有些痛苦,因为每次产生新的 xyz 时仍然需要手动干预。在非平凡的程序中,这可能是不合理的维护需求。
So instead, another way to approach this is to #include "xyz.cpp"
into the end of xyz.h:
因此,另一种解决方法是#include "xyz.cpp"
进入 xyz.h 的末尾:
// xyz.h
// ... previous content of xyz.h ...
#include "xyz.cpp"
You could of course literally bring (cut and paste it) the contents of xyz.cpp to the end of xyz.h, hence getting rid of xyz.cpp; it's a question of file organization and in the end the results of preprocessing will be the same, in that the ctor and dtor bodies will be in the header, and hence brought into any compilation request, since that would be using the respective header. Either way, this has the side-effect that now every template is in your header file. It could slow compilation, and it could result in code bloat. One way to approach the latter is to declare the functions in question, in this case the ctor and dtor, as inline, so this would require you to modify xyz.cpp in the running example.
你当然可以直接将 xyz.cpp 的内容(剪切和粘贴)带到 xyz.h 的末尾,从而摆脱 xyz.cpp;这是一个文件组织的问题,最终预处理的结果将是相同的,因为 ctor 和 dtor 主体将在头中,因此被带入任何编译请求,因为这将使用相应的头。无论哪种方式,这都会产生副作用,即现在每个模板都在您的头文件中。它可能会减慢编译速度,并可能导致代码膨胀。处理后者的一种方法是将相关函数(在本例中为 ctor 和 dtor)声明为内联函数,因此这将需要您在运行示例中修改 xyz.cpp。
As an aside, some compilers also require that some functions be defined inline inside a class, and not outside of one, so the setup above would need to be tweaked further in the case of those compilers. Note that this is a compiler issue, not one of Standard C++, so not all compilers require this. For instance, Comeau C++ does not, nor should it. Check out http://www.comeaucomputing.com/4.0/docs/userman/ati.htmlfor details on our current setup. In short, Comeau C++ supports many models, including one which comes close to what the export keyword's intentions are (as an extension) as well as even supporting export itself.
顺便说一句,一些编译器还要求在类内内联定义一些函数,而不是在类外定义,因此在这些编译器的情况下,需要进一步调整上述设置。请注意,这是一个编译器问题,而不是标准 C++ 之一,因此并非所有编译器都需要此问题。例如,Comeau C++ 没有,也不应该。查看http://www.comeaucomputing.com/4.0/docs/userman/ati.html了解我们当前设置的详细信息。简而言之,Comeau C++ 支持许多模型,包括一个接近 export 关键字意图的模型(作为扩展),甚至支持 export 本身。
Lastly, note that the C++ export keyword is intended to alleviate the original question. However, currently Comeau C++ is the only compiler which is being publicized to support export. See http://www.comeaucomputing.com/4.0/docs/userman/export.htmland http://www.comeaucomputing.com/4.3.0/minor/win95+/43stuff.txtfor some details. Hopefully as other compilers reach compliance with Standard C++, this situation will change. In the example above, using export means returning to the original code which produced the linker errors, and making a change: declare the template in xyz.h with the export keyword:
最后,请注意 C++ export 关键字旨在缓解原始问题。但是,目前 Comeau C++ 是唯一被公开支持导出的编译器。有关详细信息,请参阅http://www.comeaucomputing.com/4.0/docs/userman/export.html和http://www.comeaucomputing.com/4.3.0/minor/win95+/43stuff.txt。希望随着其他编译器符合标准 C++,这种情况将会改变。在上面的示例中,使用 export 意味着返回产生链接器错误的原始代码,并进行更改:使用 export 关键字在 xyz.h 中声明模板:
// xyz.h
export
// ... ORIGINAL contents of xyz.h ...
The ctor and dtor in xyz.cpp will be exported simply by virtue of #includeing xyz.h, which it already does. So, in this case you don't need xyztir.cpp, nor the instantiation request at the end of xyz.cpp, and you don't need the ctor or dtor manually brought into xyz.h. With the command line shown earlier, it's possible that the compiler will do it all for you automatically.
xyz.cpp 中的 ctor 和 dtor 将简单地通过 #includeing xyz.h 导出,它已经这样做了。因此,在这种情况下,您不需要 xyztir.cpp,也不需要 xyz.cpp 末尾的实例化请求,也不需要将 ctor 或 dtor 手动引入 xyz.h。使用前面显示的命令行,编译器可能会自动为您完成所有工作。
回答by Martin Beckett
See thisexplanation for its use
请参阅此说明以了解其用途
Quite a few compilers don't support it either because it's too new or in the case of gcc - because they disaprove.
相当多的编译器不支持它,要么因为它太新,要么在 gcc 的情况下 - 因为他们不赞成。
This post describes standard support for many compilers. Visual Studio support for new C / C++ standards?
这篇文章描述了对许多编译器的标准支持。 Visual Studio 是否支持新的 C/C++ 标准?
回答by Greg Rogers
See hereand herefor Herb Sutter's treatment of the subject.
请参阅此处和此处了解 Herb Sutter 对该主题的处理。
Basically: export has been implemented in only onecompiler - and in that implementation, export actually increases the coupling between template definition and declaration, whereas the only point in introducing export was to decrease this coupling.
基本上:导出仅在一个编译器中实现 - 在该实现中,导出实际上增加了模板定义和声明之间的耦合,而引入导出的唯一目的是减少这种耦合。
That's why most compilers don't bother. I would have thought they would have just removed export from the language in C++0x, but I don't think they did. Maybe some day there will be a good way to implement export that has the intended use.
这就是为什么大多数编译器不会打扰的原因。我原以为他们会在 C++0x 中从语言中删除导出,但我认为他们没有。也许有一天会有一个很好的方法来实现具有预期用途的导出。
回答by MSalters
Export is a feature that introduces a circular dependency between linker and compiler. As others noted, it allows one translation unit to contain the definition of a template used in another. The linker will be the first to detect this, but it needs the compiler for the instantiation of the template. And this involves real hard work, like name lookup.
导出是一种在链接器和编译器之间引入循环依赖的功能。正如其他人指出的那样,它允许一个翻译单元包含另一个使用的模板的定义。链接器将首先检测到这一点,但它需要编译器来实例化模板。这涉及真正的艰苦工作,例如名称查找。
Comeau introduced it first, about 5 years ago IIRC. It worked quite well on the first beta release I got. Even testcases like A<2> using B<2> using A<1> using B<1> using A<0>, worked, if templates A and B came from different TU's. Sure, the linker was repeatedly invoking the compiler, but all name lookups worked OK. Instantiation A<1> found names from A.cpp that were invisible in B.cpp.
Comeau 大约在 5 年前 IIRC 首次引入了它。它在我得到的第一个 beta 版本上运行良好。即使像 A<2> 使用 B<2> 使用 A<1> 使用 B<1> 使用 A<0> 这样的测试用例也可以工作,如果模板 A 和 B 来自不同的 TU。当然,链接器反复调用编译器,但所有名称查找都正常。实例化 A<1> 从 A.cpp 中找到了在 B.cpp 中不可见的名称。
回答by Rodyland
To put it simply:
简而言之:
export
lets you separate the declaration (ie. header) from the definition (ie. the code) when you write your template classes. If export
is not supported by your compiler then you need to put the declaration and definition in one place.
export
允许您在编写模板类时将声明(即标题)与定义(即代码)分开。如果export
您的编译器不支持,那么您需要将声明和定义放在一个地方。
回答by Nemanja Trifunovic
回答by KTC
The only compilers that support exported templates at the moment (as far as I know) are Comeau, the one that came with Borland C++ Builder X but not the current C++ Builder, and Intel (at least unofficially, if not officially, not sure).
目前(据我所知)唯一支持导出模板的编译器是 Comeau,Borland C++ Builder X 附带的编译器,但不是当前的 C++ Builder,还有 Intel(至少是非正式的,如果不是正式的,不确定) .