Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

template specialization multiply defined symbols

I know I'm missing something easy here but I've got a templated member function of a class which I've specialised.

class 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.

This is defined in my header file (as templates should be) but when I go to compile, I get a bunch of multiple defined symbols errors, such as:

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

I can fix it by inlining the method but I don't think that should be necessary... what am I missing?

EDIT: I'm using Visual Studio 2010

like image 417
Jamie Cook Avatar asked Dec 15 '10 05:12

Jamie Cook


People also ask

Where do I put specialization templates?

Try putting the specializations in the header file as well. Put a inline keyword at the definitions.

What is the specialty of a template function give example?

Template in C++is a feature. We write code once and use it for any data type including user defined data types. For example, sort() can be written and used to sort any data type items. A class stack can be created that can be used as a stack of any data type.

What is an explicit specialization of a function template?

An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.

What is template specialization in C++ with example?

Template Specialization (C++) The result is a template parameterized on the remaining types. A template has only one type, but a specialization is needed for pointer, reference, pointer to member, or function pointer types. The specialization itself is still a template on the type pointed to or referenced.

Which template types can be fully specialized?

Any of the following can be fully specialized: Explicit specialization may be declared in any scope where its primary template may be defined (which may be different from the scope where the primary template is defined; such as with out-of-class specialization of a member template) .

How do I create a partial specialization of a template collection?

If you have a template collection class that takes any type T, you can create a partial specialization that takes any pointer type T*. The following code demonstrates a collection class template Bag and a partial specialization for pointer types in which the collection dereferences the pointer types before copying them to the array.


2 Answers

The full specialization is no longer a template. It's a concrete function. As such it needs to be (implicitly or explicitly) declared inline. The easiest is to add that keyword before the return type specification.

That said, the presented code does not correspond to your error message.

Your error message talks about return type std::string, not return type int.

like image 80
Cheers and hth. - Alf Avatar answered Sep 18 '22 16:09

Cheers and hth. - Alf


As Alf noted, the full specialization is no longer a template. However, I am not sure it has to be defined inline. You should also be able to split the declaration and definition.

I.e. In your header have:

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

and in the implementation have:

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

I also had thought that by rights the templated definition should also be explicitly inline (I always have done so) but would not be too surprised if a given compiler was lax in applying the ODR for templates. I'd be interested to see the standard reference that states otherwise.

like image 42
Keith Avatar answered Sep 20 '22 16:09

Keith