将模板类与引用非类型模板参数一起使用时出现链接器错误

Linker error when using template class with a reference non-type template parameter

本文关键字:错误 链接 参数 引用 类型 一起      更新时间:2023-10-16

我正在开发一个C++库,我需要在其中向用户提供类模板。

此类的模板参数是一个引用。但是,我收到链接器错误。下面是一个最小的测试用例:

测试.hh

#ifndef TEST_HH_
#define TEST_HH_
template <double const& val>
struct A{};
constexpr double zero = 0.;
A<zero> foo();
#endif // TEST_HH_

测试.cpp

#include "test.hh"
A<zero> foo(){ return A<zero>(); }

主.cpp

#include "test.hh"
int main()
{
    foo();
}

编译这段代码时,我收到警告:

'A<zero> foo()' used but never defined

后跟链接器错误:

undefined reference to foo()

我试图用 int 替换双精度

template <int val>
struct A{};

它链接(将int作为参数 ofc 传递时),但我真的需要一个double.

当模板类涉及链接错误时,我也尝试了一种常见的解决方案,我在 test.hh 中实现了 foo() 函数而不是 test.cpp ,但我想避免将所有代码放在标题中。

很高兴这没有链接!可能会更糟...

问题基本上是test.cppmain.cpp都有名为 ::zero 的不同对象。这是违反 ODR 的 - 该变量有多个定义,并且最终A<zero>技术上是不同的类型,因为A的模板参数val是对不同翻译单元中不同对象的引用。

希望这个解释能清楚地说明为什么A<int>工作正常。

在 C++17 中,您需要:

inline constexpr double zero = 0.;

在 C++14 中,您要么需要在其中一个翻译单元中添加定义,要么执行其他一些魔法,例如::zero本身是对某个静态模板变量或其他 voodoo 的引用。

相关文章: