C ++ Variadic模板“多个定义”/“已定义”问题

时间:2014-10-23 07:25:24

标签: c++ visual-studio-2013 variadic-templates multiple-definition-error

最近发现了模板,我一直在努力掌握它们,并且遇到了我真正想要实现的用法;但是我尝试了很多东西,但一直都会遇到错误。

我正在尝试创建一个可以按任意顺序一次获取多种类型参数的函数。

(我正在使用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"

的.cpp文件

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;
}

我错过了什么导致此错误?

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

1 个答案:

答案 0 :(得分:3)

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

inline添加到两个特化项中,或者只在标题中保留它们的声明并将定义移动到某个.cpp文件。

主模板定义正常,应保留在标题中。

一般建议是避免功能模板特化。您可以使用普通的非模板重载:

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