C++ 可变参数模板"multiple definitions"/"already defined"问题

C++ Variadic Template "multiple definitions"/"already defined" Issue

本文关键字:definitions already defined 问题 multiple C++ 变参 参数      更新时间:2023-10-16

最近发现了模板,我一直在努力掌握它们,并发现了我真正想实现的模板用法;但我尝试了很多东西,却总是出错。

我正在尝试创建一个函数,它可以以任何顺序同时接受多种类型的参数。

(我使用的是VS 2013。)

我现在有一个"已定义"错误(仅当在多个文件中包含tem.h时):

准确的第一个错误(其余的基本相同,只是每次测试…过载?):

Error 1 error LNK2005: "void __cdecl test<struct A>(struct A *)" (??$test@UA@@$$$V@@YAXPAUA@@@Z) already defined in main.obj c:UsersUserdocumentsvisual studio 2013ProjectsTemplateTestTemplateTestfoo.obj TemplateTest

foo只是一个.cpp文件,只包含:#include "tem.h"

tem.h:

#ifndef TEM_H
#define TEM_H
struct A {};
struct B {};
#include <iostream>
template<typename First, typename... Rest>
void test(First *t, Rest&&... args){
    test(t);
    test(std::forward<Rest>(args)...);
}
template<>
void test<A>(A *val){
    std::cout << "Handled A" << std::endl;
}
template<>
void test<B>(B *val){
    std::cout << "Handled B" << std::endl;
}
#endif

main.cpp:

#include <iostream>
#include "tem.h"
int main(int argc, char *argv[]){
    std::cout << "running test..." << std::endl;
    A a;
    B b;
    test(&a, &b);
    return 0;
}

导致此错误的原因是我缺少什么?

编辑:使每个测试实例内联可以防止错误,但我不认为这是最好的解决方案

函数模板专业化本身并不是模板,它们是具有奇特语法的普通函数。与任何其他正常函数一样,除非使用inline关键字,否则不应在头文件中定义它们。

要么将inline添加到这两个专门化中,要么只在头中保留它们的声明,并将定义移动到某个.cpp文件中。

主模板定义是可以的,应该原封不动地保留在标题中。

不过,一般建议是避免函数模板专业化。您可以使用正常的非模板重载:

void test (A*);
void test (B*);