最近发现了模板,我一直在努力掌握它们,并且遇到了我真正想要实现的用法;但是我尝试了很多东西,但一直都会遇到错误。
我正在尝试创建一个可以按任意顺序一次获取多种类型参数的函数。
(我正在使用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:\Users\User\documents\visual studio 2013\Projects\TemplateTest\TemplateTest\foo.obj TemplateTest
foo只是一个仅包含:#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;
}
我错过了什么导致此错误?
编辑: 使每个测试实例内联可以防止错误,但我认为这不是最好的解决方案
答案 0 :(得分:3)
函数模板特化本身不是模板,它们是具有花哨语法的普通函数。与任何其他常规函数一样,除非使用inline
关键字,否则不应在头文件中定义它们。
将inline
添加到两个特化项中,或者只在标题中保留它们的声明并将定义移动到某个.cpp文件。
主模板定义正常,应保留在标题中。
一般建议是避免功能模板特化。您可以使用普通的非模板重载:
void test (A*);
void test (B*);