C++ 模板专用化多定义符号

C++ 模板专用化多定义符号,c++,templates,linker,C++,Templates,Linker,我知道我在这里遗漏了一些简单的东西,但我有一个我专门研究的类的模板成员函数 MyClass { template<typename T> T GetTFromVariable(shared_ptr<TOtSimpleVariable> v, string s); } template<typename T> T MyClass::GetTFromVariable(shared_ptr<TOtSimpleVariable> v, strin

我知道我在这里遗漏了一些简单的东西,但我有一个我专门研究的类的模板成员函数

MyClass
{
    template<typename T> T GetTFromVariable(shared_ptr<TOtSimpleVariable> v, string s);
}

template<typename T>
T MyClass::GetTFromVariable(shared_ptr<TOtSimpleVariable> v, string s)
{
    throw std::runtime_error("Don't know how to convert " + ToString(v->GetString()));
}

template<>
int MyClass::GetTFromVariable<int>(shared_ptr<TOtSimpleVariable> v, string s)
{
    return v->GetInteger();
}

template<>
string MyClass::GetTFromVariable<string>(shared_ptr<TOtSimpleVariable> v, string s)
{
    return v->GetString();
}

// etc for other specialisations.
MyClass
{
模板T GetTFromVariable(共享的ptr v,字符串s);
}
模板
T MyClass::GetTFromVariable(共享的\u ptr v,字符串s)
{
抛出std::runtime_错误(“不知道如何转换”+ToString(v->GetString());
}
模板
int MyClass::GetTFromVariable(共享的\u ptr v,字符串s)
{
返回v->GetInteger();
}
模板
字符串MyClass::GetTFromVariable(共享的\u ptr v,字符串s)
{
返回v->GetString();
}
//等其他专业。
这是在我的头文件中定义的(模板应该是这样的),但是当我去编译时,我得到了一堆相互定义的符号,一个典型的错误是:

     OtCustomZenith_logic.lib(PtPathOutput.obj) : error LNK2005: "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall MyClass::GetTFromVariable<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class boost::shared_ptr<class TOtSimpleVariable>,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??$GetTFromVariable@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@CommandProperties@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$shared_ptr@VTOtSimpleVariable@@@boost@@V12@@Z) already defined in TableFareSystem_test.obj
OtCustomZenith_logic.lib(PtPathOutput.obj):错误LNK2005:“public:class std::basic_string\uu thiscall MyClass::GetTFromVariable(class boost::shared_ptr,class std::basic_string)”(??$GetTFromVariable@V?$basic_string@DU?$char_traits@D@性病病毒$allocator@D@2@@std@@@CommandProperties@@QAE?AV?$basic_string@DU?$char_traits@D@性病病毒$allocator@D@2@@std@@V?$shared_ptr@VTOtSimpleVariable@@@boost@@V12@@Z)已在TableFareSystem_test.obj中定义
我可以通过内联方法来修复它,但我认为这不必要……我忘记了什么


编辑:我正在使用Visual Studio 2010

完全专业化不再是一个模板。它是一个具体的函数。因此,它需要(隐式或显式)声明为
内联
。最简单的方法是在返回类型规范之前添加该关键字

也就是说,显示的代码与错误消息不对应


您的错误消息涉及返回类型
std::string
,而不是返回类型
int


Cheers&hth.,

我建议您从代码中删除以下实现,这样,如果T不是int,编译器就可以在编译时自己生成错误。早期检测错误比延迟检测(在运行时完成)更好

模板
T MyClass::GetTFromVariable(共享的\u ptr v,字符串s)
{
抛出std::runtime_错误(“不知道如何转换”+ToString(v->GetString());
}
在讨论这件事时,有一个完全相似的主题/问题。请看一下:


正如阿尔夫所指出的,完全专业化不再是一个模板。 但是,我不确定它是否必须内联定义。 您还应该能够拆分声明和定义

即,在标题中有:

template<> 
int MyClass::GetTFromVariable<int>(shared_ptr<TOtSimpleVariable> v, string s);
模板
int MyClass::GetTFromVariable(共享的\u ptr v,字符串s);
在实施过程中:

template<>
int MyClass::GetTFromVariable<int>(shared_ptr<TOtSimpleVariable> v, string s)
{
    return v->GetInteger();
}
模板
int MyClass::GetTFromVariable(共享的\u ptr v,字符串s)
{
返回v->GetInteger();
}

我还认为,根据权利,模板定义也应该显式内联(我一直这样做)但是,如果给定的编译器对模板的ODR应用不严格,我也不会感到太惊讶。我很想看看标准参考,它说明了其他情况。

您使用的是什么工具链?GCC?可视化的东西?如果是GCC,构建和链接行是什么样子的?“您的错误消息涉及返回类型
std::string
,而不是返回类型
int
”…这意味着它使用的是第一个(常规)模板,该模板返回类型T(在本例中为
std::string
)@Mike:不,这意味着提供的代码与错误消息不匹配。我可以猜测OP有几个明确的物种,而不仅仅是一个,并且他选择了一个任意的错误消息。但这只是一个猜测。我是说,当你寻求帮助时,尽量精确,不要引入无关的问题。谢谢@alf,你是正确的,我是我更新了问题以更准确地反映问题。很抱歉措辞不准确。我只是在谈论OP的代码,它的定义在头文件中。感谢澄清!干杯,将专门化从头文件移动到单个.cpp文件意味着需要编译并链接到.obj or.lib会损害可用性。最好按照@alf的建议将其保持在内联状态。因此,我不赞成你的答案。最好将其删除,但使用静态断言(false,“解释问题和解决方案”)。这将有助于开发人员了解错误结果会导致什么。
template<>
int MyClass::GetTFromVariable<int>(shared_ptr<TOtSimpleVariable> v, string s)
{
    return v->GetInteger();
}