未找到外部声明的模板专用函数

extern declared template specialized function not found

我正在尝试实现 json 序列化库的克隆 nlohmann::json 作为一种学习经验,但我在使用用户定义的界面时遇到了问题 (json <->用户类型)转换。

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

当我直接定义这些函数时,它工作正常,但是当我尝试为多种类型(在本例中为 class S)创建模板定义时,链接器找不到定义。

我已经尝试为模板化 class 的各个实例显式实例化函数,尽管我更愿意避免在最终产品中这样做。

我猜这与模板函数与自由函数的签名不同这一事实有关,但我不知道我能做些什么来让它工作。我错过了什么?我也无法在 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);
}

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