未找到外部已声明的模板专用功能

时间:2018-11-13 03:35:28

标签: c++ linker-errors

我正在尝试实现json序列化库nlohmann :: json的克隆作为学习体验,并且我在用户定义(json <->用户类型)转换的接口方面遇到麻烦。

基本上我希望用户能够重载两个函数:to_json(json&,const Type&)和from_json(const json&,Type&)。然后,库将使用重载分辨率在模板化的operator =和一个参数构造函数中调用这些函数。

当我只是直接定义这些函数时,效果很好,但是当我尝试为多种类型(在本示例中为S类)创建模板定义时,链接器找不到该定义。

我试图显式实例化模板化类的各个实例的功能,尽管我希望避免在最终产品中这样做。

我猜想这与以下事实有关:模板化函数与自由函数没有相同的签名,但是我不知道我能做些什么来使其工作。我想念什么?我也无法在Google上找到结果,所以它是记录的模式还是反模式?

谢谢。下面,我尝试通过一个简短的示例将问题最小化。

Class.hpp

#pragma once
#include <cstdio>

template<size_t i>
class S {
    size_t n = i;
};

template<size_t i>
void g(const S<i>& s) {
    printf("S<%u>\n", i);
}

Class.cpp

#include "Class.hpp"

template void g<10>(const S<10>&); // <-- Even with explicitly instanciation

void g(const bool& b) {
    printf("%s\n", b ? "true" : "false");
}

main.cpp

#include "Class.hpp"

template<typename T>
void f(T t) {
    extern void g(const T&);
    g(t);
}

int main(int, char**) {
    S<10> s;
    //f(s); <-- linker error: void g(class S<10> const &) not found.
    f(false);
}

1 个答案:

答案 0 :(得分:3)

一旦找到g声明,就会在g(t)调用中对extern void g(const T&);的名称查找停止;它永远不会看到功能模板的声明。因此,编译器使用g生成对名为const S<10>&的常规非模板函数的调用。但是您的程序中未定义此类功能-因此出现链接器错误。