当前位置: 首页 > 知识库问答 >
问题:

模板专门化在Windows上导致与MinGW的链接错误,而不是在Linux上导致与GCC的链接错误

牧业
2023-03-14

以下构建设置在使用GCC(4.6.3)的Linux上运行良好,但在使用GCC(4.7.2)的MinGW上则不然。

$ cat Makefile 
all:
        g++ -c foo.cpp
        g++ -c bar.cpp
        g++ bar.o foo.o -o bar
$ cat foo.h 
#ifndef FOO_H
#define FOO_H

#include <iostream>

template <typename T>
void foo(T x) {
    std::cout << "Hello World!" << std::endl;
}
#endif
$ cat foo.cpp
#include "foo.h"
template <>
void foo(int x) {
    std::cout << "Hello Int!" << std::endl;
}
$ cat bar.cpp 
#include "foo.h"

int main() {
    foo <int> (1);
}

在 Linux 上,我们有:

$ make
g++ -c foo.cpp
g++ -c bar.cpp
g++ bar.o foo.o -o bar

$ ./bar
Hello Int!

这正是我所期待的。在Windows上,我们有

$ make
g++ -c foo.cpp
g++ -c bar.cpp
g++ bar.o foo.o -o bar
foo.o:foo.cpp:(.text+0x0): multiple definition of `void foo<int>(int)'
bar.o:bar.cpp:(.text$_Z3fooIiEvT_[__Z3fooIiEvT_]+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
make: *** [all] Error 1

我怀疑这和弱符号有关。也就是说,Linux我们在foo. o有

00000000 T _Z3fooIiEvT_

而且在baro

00000000 W _Z3fooIiEvT_

而在Windows上,我们在foo.o中有这样的功能

00000000 T __Z3fooIiEvT_

而且在baro

00000000 T __Z3fooIiEvT_

因此,没有弱符号可以覆盖。

解决这个问题的最好方法是什么?在实际案例中,我有一个头foo. h,其中包含许多模板定义。其中一些,我进行了专门化,并将这些定义放在foo.cpp中,稍后将其编译成一个库。然后,我将头和库交给用户。如果可能,我总是想在foo库中使用专门化。如果专门化不存在,我想在foo头中使用模板定义。

编辑

foo.h的以下修改似乎可以解决问题

$ cat foo.h 
#ifndef FOO_H
#define FOO_H

#include <iostream>

template <typename T>
void foo(T x) {
    std::cout << "Hello World!" << std::endl;
}
template <>
void foo(int x);
#endif

基本上,foo 的 int 版本的原型需要在标头中。这与BoBTFish的注释相吻合,即该标准要求“在首次使用之前应声明专业化”。无论如何,这是设置专业化库的最佳方式吗?

共有2个答案

翟英达
2023-03-14

您可以安装(在Windows和Linux上)最新的GCC(今天是4.8.1)并使用C 11的extern模板功能。

王弘和
2023-03-14

我不知道编译器的复杂性,但你违反了标准:

14.7.3明确专业化:

6 如果模板、成员模板或类模板的成员是显式专用的,则该专用化应在首次使用该专用化之前声明,该专用化将导致隐式实例化发生,在发生此类使用的每个翻译单元中;无需诊断。

所以你的程序格式不正确。

 类似资料:
  • 考虑以下头文件和源文件: 我在

  • 问题内容: 我正在尝试构建Boost并生成dll,但是我所做的任何事情都无法解决问题。 这是我得到的: 创建库bin.v2 \ libs \ thread \ build \ msvc-11.0 \ dbg \ adrs-mdl-32 \ async- excpt-on \ thrd-mlt \ boost_thread-vc110-mt-gd-1_53.lib和对象bin.v2 \ libs \

  • 在SO上回答另一个问题时,我遇到了一个有点可疑的gcc编译器错误。令人不快的片段是 谁的最后一行给出了著名的警告 好友声明'

  • 我有个例外 2018-11-01 21:05:49.122错误31446---[nio-8080-exec-1]O.A.C.C.C.[.[.[/].[dispatcherServlet]:servlet.Service()在路径[]上下文中的servlet[dispatcherServlet]引发异常[请求处理失败;嵌套异常为org.springframework.web.multipart.ma

  • 我认为我的模板使用不当,但我不知道我做错了什么。这就像模板链表无法确定它需要使用我的术语类一样。 名单- 以下是Visual Studio 2012的确切错误: > 错误LNK1120:1未解决的外部C:\用户\迈克尔\文档\魔术公文包\尚普兰\课程工作\数据结构\pa2\调试\pa2.exe 标题。H 功能。cpp 链接列表。H 术语h