模板特化乘法定义符号

时间:2010-12-15 05:27:46

标签: 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, 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.

这是在我的头文件中定义的(因为模板应该是)但是当我去编译时,我得到了一堆多个定义的符号,代表这样的错误是:

     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

我可以通过内联方法来修复它,但我认为不应该这样做......我忘了什么?

编辑:我正在使用Visual Studio 2010

3 个答案:

答案 0 :(得分:29)

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

也就是说,显示的代码与您的错误消息不符。

您的错误消息说明了返回类型std::string,而不是返回类型int

干杯&amp;第h。,

答案 1 :(得分:28)

正如Alf所说,完全专业化不再是模板。 但是,我不确定是否要内联定义。 您还应该能够拆分声明和定义。

即。在你的标题中有:

template<> 
int MyClass::GetTFromVariable<int>(shared_ptr<TOtSimpleVariable> v, string s);

并且在实施中有:

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

我还认为,通过权限,模板化的定义也应该是显式的内联(我总是这样做)但如果给定的编译器在为模板应用ODR时松懈,也不会太惊讶。我有兴趣看到另外说明的标准参考。

答案 2 :(得分:3)

我建议你完全从你的代码中删除以下实现,这样如果T不是int ,编译器就会在编译时生成错误。早期检测错误优于延迟检测(在运行时完成)。

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

讨论这个问题的主题/问题完全相同。请看一下:

Partial template specialization for specific type, c++