【问题标题】:C++ Variadic Template "multiple definitions"/"already defined" Issue [duplicate]C ++可变参数模板“多个定义”/“已定义”问题[重复]
【发布时间】:2014-10-23 07:25:24
【问题描述】:

最近发现了模板,我一直在尝试很好地掌握它们,并遇到了我非常想实现的它们的用法;但是尝试了多种方法后,我不断收到错误。

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

(我使用的是 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 只是一个 .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;
}

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

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

【问题讨论】:

  • 究竟已经定义了什么?始终显示完整的未编辑错误消息。
  • @n.m. Error 1 error LNK2005: "void __cdecl test&lt;struct A&gt;(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 只是一个 c++ 源文件,顶部有 #include "tem.h"
  • 这个问题在 StackOverflow 上有 4,206,904 个重复项
  • @JonathanWakely 最初它的格式是为了解决这个问题,即使尝试解决方案发现我仍然遇到错误,但它被标记为一个问题的重复,该问题的解决方案已经尝试过,但有错误
  • 查看您的原始问题,问题出在未在标题中定义且未在tem.cpp 中实例化的主模板(可变参数模板)上,因此您遇到了缺少定义错误。您通过在标题中定义 everything 来修复它的尝试扭转了这种情况,这会产生多个定义错误。解决方案是内联定义所有内容(并将inline 放在特化上!)或将主要(即非特化)函数模板放在标题中,并将特化放在 .cpp 文件中。

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


【解决方案1】:

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

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

主模板定义没问题,应该原封不动地留在表头中。

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

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

【讨论】:

  • 这是我第二次尝试的。它给了我一个“未解决的外部符号”错误,当我将它作为问题发布时,它被标记为重复:stackoverflow.com/questions/495021/…
  • 我试图实现的是一个函数,我可以将多个对象传递给不同类型的对象,并根据它们的类型进行处理。据我所知,仅通过重载是无法实现的
  • @G.Chi 再说一次,没有人说过你不能使用模板。可变参数模板可以保留。您尝试的两个特化不必是特化的。它们可以只是内联重载。
  • 您可能已经尝试在 .cpp 文件中同时实现主模板和特化,这是错误的。
猜你喜欢
  • 1970-01-01
  • 2017-04-10
  • 2015-07-11
  • 1970-01-01
  • 2013-10-27
  • 1970-01-01
  • 2012-12-21
  • 1970-01-01
相关资源
最近更新 更多