首页 > 解决方案 > OSX clang++:架构 x86_64 的未定义符号,用于 cpp 文件中显式实例化的模板

问题描述

我在 .h 文件中定义了模板类,在 .cpp 文件中定义了模板方法。此 .cpp 文件还包含通过template clas Class<type>.

此用例在 VS2019 上与在 GCC (7.4.0) 上一样正常工作。但是,它不适用于带有 clang++ 的 OSX(Apple LLVM 版本 10.0.0 clang-1000.11.45.5)。

根据文档,我相信这是一个有效的代码。有什么办法让它在 OSX clang 下工作?

我不想将所有实现移动到 .h 因为更好的可读性并且因为我只需要两个/三个模板实例化。

这是我的测试文件:

test.h

#pragma once

template <class T>
class CTemplateTest
{
public:
  int Test();
};

test.cpp

#include "test.h"

template class CTemplateTest<int>;
template class CTemplateTest<double>;

template <class T>
int CTemplateTest<T>::Test()
{
    return 42;
}

main.cpp

#include "test.h"
int main(int argc, char** argv)
{

    CTemplateTest<int> t1;
    CTemplateTest<double> t2;

    t1.Test();
    t2.Test();
}

output

Undefined symbols for architecture x86_64:
  "CTemplateTest<double>::Test()", referenced from:
      _main in main.o
  "CTemplateTest<int>::Test()", referenced from:
      _main in main.o
ld: symbol(s) not found for architecture x86_64

谢谢你的帮助。

标签: c++templatesgccclang++

解决方案


成员函数未实例化。这并不奇怪,因为您定义CTemplateTest<T>::Test. 将显式实例化移到test.cpp

template <class T>
int CTemplateTest<T>::Test()
{
    return 42;
}

template class CTemplateTest<int>;
template class CTemplateTest<double>;

我建议你在标题中添加一个显式的实例化声明

template <class T>
class CTemplateTest
{
public:
  int Test();
};

extern template class CTemplateTest<int>;
extern template class CTemplateTest<double>;

这指示编译器在使用特定特化时放弃大部分隐式实例化。它会知道完整的定义在别处。

此外,它还具有良好的文档目的。现在只需阅读标题即可知道支持的类型。


推荐阅读