【问题标题】:OSX clang++: Undefined symbols for architecture x86_64 for explicitely instantiated template in cpp fileOSX clang++:架构 x86_64 的未定义符号,用于 cpp 文件中显式实例化的模板
【发布时间】:2020-06-11 10:46:44
【问题描述】:

我在 .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

感谢您的帮助。

【问题讨论】:

  • 这可能是因为在模板或显示的代码中没有定义名为“TestAdd”的方法。不过,在这种情况下,我预计会出现不同的编译错误。显而易见的结论是显示的代码不是正在编译的真实代码,因此任何人可以提供的任何可能的解释都只是猜测和随机猜测。我不确定我是否理解为什么没有显示产生此编译错误的实际代码,而是显示了完全伪造的代码。
  • 抱歉,TestAdd 是我为 SO 问题更新的原始代码。它现在更新了(但我相信这不是那么大的错误!;-))

标签: c++ templates gcc clang++


【解决方案1】:

成员函数未实例化。这并不奇怪,因为您在定义CTemplateTest&lt;T&gt;::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>;

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

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

【讨论】:

  • 你是对的!我也想通了;-)。感谢您提供有关标题放置的信息。这是个好主意。
【解决方案2】:

好的,我会回答我的问题。

由于我不明白 clang++ 在所有其他代码之后需要这些显式实例化的原因。

所以,test.cpp 文件的正确格式是:

#include "test.h"

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

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

我希望这对其他人也有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 2016-12-02
    • 2018-01-30
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 2015-10-09
    相关资源
    最近更新 更多