使用export关键字与模板

40

据我所了解,“export”关键字可用于通过头文件公开模板类或函数签名,并将实际实现抽象到库文件中。
请问有人能提供一个实际的示例程序来展示如何做到这一点吗?
在使用此功能时,是否存在任何缺点或需要注意的重要事项?

编辑:根据答案的回答,提出一个后续问题。如答案所述,“export”已在C++0x中被弃用,并且即使是针对C++03x,编译器也很少支持。在这种情况下,有什么方法可以隐藏实际的实现以及只通过头文件公开声明,以便最终用户可以知道公开API的签名,但不能访问实现相同的源代码?


1
我不知道目前是否所有的编译器都支持它。我认为Comeau是少数几个具备该功能的编译器之一。 - jonsca
1
这个 C++ FAQ-Lite 条目似乎回答了你的问题。 - Björn Pollex
C++0x中已经废弃了export关键字,而且在C++03中也不可用(除了Comeau编译器)。 - Alexandre C.
@Alexandre C:它曾被考虑过要废弃(http://herbsutter.com/2009/10/23/deprecating-export-considered-for-iso-c0x/),但我没有完全跟进这件事。 - Matthieu M.
4
正如答案中提到的,"export" 在 C++0x 中已经被弃用。如果这些答案这样说,那么它们是不正确的。这个关键字已经完全从 C++0x 中删除了。 - Johannes Schaub - litb
7个回答

51

注意:本答案关于C++20之前export的历史用途;C++20将该关键字重新用于模块。

首先:大多数编译器(包括gcc、Clang和Visual Studio)不支持export关键字。

它只在EDG前端实现,并且只有使用它的编译器(如Comeau和icc)支持此功能。EDG的实现者反馈非常简单:这花费了我们时间,非常复杂,我们建议不要实现它(1),因此它已在C++0x中被删除。

现在,标准允许(至少gcc实现了以下内容):

  • 在头文件中声明模板函数的特定版本
  • 在单个源文件中定义此专业化

并使其行为与常规函数相同。

注意:正如Johannes在评论中指出的那样,如果在头文件中定义了函数的全特化,则必须将其标记为inline,否则链接器将会报错。

编辑:

(1) 最终找到我的参考文献为什么我们负担不起使用export(PDF),由Tom Plum编写,由Edison Design Group的Steve Adamczyk、John Spicer和Daveed Vandevoorde进行审查,他们最初在EDG前端中实现了它。


1
那其实不是导致 C++0x 废弃的那篇论文。(它是一篇2003年的论文)事实上,这个提案被投票否决了,而且反对的票数相当多(如果我没记错,在非正式投票中约有2/3的人支持保留 export,但没有进入正式投票)。 - MSalters
@MSalters: 我从来没有打算暗示那个,我会让它更清晰 :) - Matthieu M.
1
声明一个模板函数的专门版本,将其放在头文件中,在单个源代码文件中定义该专门版本。唔,这正是规范要求的内容。函数模板的显式特化是函数(不是模板),实际上不能在头文件中可靠地定义,除非它们是内联的(否则,将导致多个定义错误)。我是否误解了您的意思? - Johannes Schaub - litb
...如果相互包含C++的内联模板,结果就会压倒性地灾难性。 :-( - peterh
导出功能回归,使用C++模块(C++20)- https://en.cppreference.com/w/cpp/language/modules - ProfNandaa
1
@ProfNandaa:很好的观点;添加了免责声明,以明确本答案(和问题)讨论的是C++20之前的“export”,以避免混淆。 - Matthieu M.

15

1
该关键字未使用且被保留。看起来更像是“尚未实现”而不是“已过时”。无论如何,谢谢。 - rr-
4
实际上,在 C++2003 中,定义了功能导出关键字。基本上没有编译器实现了这个功能。在 C++2011 中,该功能从 C++ 标准中删除了。导出关键字仍然被保留,但没有功能。但是,发帖者显然是在询问与导出关键字相关的 C++2003 功能,而这已经从 C++ 中删除了。 - ltc
我明白了,这就解释了为什么它一直没有被使用。 - rr-
2
它又回来了,这次是与模块一起。 - Dan M.

5
由于几乎没有编译器支持export,因此很难提供示例程序。g++会报告一个警告,指出它不被支持,并且我IRC在Visual Studio中甚至不能编译。此外,export在C++0x中已经被弃用,这意味着未来的编译器可能根本不支持它。
有关如何在少数支持它的编译器(即Comeau C ++)中使用export的讨论,请查看此链接,该链接还介绍了为什么实现export很困难。
如果这听起来像是反对export的主要言论,那么请接受我的道歉。我保证我不讨厌export!只是它得不到广泛支持,作为程序员你不能真正依赖它。

1

0

我读了一篇文章,标题大概是“不支持导出”,而且它也无法实现你想要的功能。

唯一能做到你想要的就是全面专业化,正如先前所说。但更重要的是,如果你看不到库的源代码,那么你就无法编译它。这意味着你无法接受来自库的动态内存,因为没有保证你将使用与其相匹配的 delete。例如,如果我的代码是 debug 模式而库是 release 模式,删除器将不匹配 new。你可以使用 shared_ptr 并提供删除器,但那是 TR1,并没有导出。


0

C++11现在有“extern templates”,这已经得到了现代编译器的良好支持。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接