Специализированные шаблоны

Я знаю, что мне не хватает чего-то легкого здесь, но у меня есть шаблонная функция-член класса, который я специализировал.

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> >)" ([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@@[email protected]@[email protected]@Z) already defined in TableFareSystem_test.obj

Я могу исправить это, введя эти методы, но я не думаю, что это необходимо... что я забыл?

EDIT: я использую Visual Studio 2010

Ответы

Ответ 1

Как отметил Альф, полная специализация уже не является шаблоном. Тем не менее, я не уверен, что он должен быть определен inline. Вы также должны иметь возможность разделить декларацию и определение.

т.е. В вашем заголовке есть:

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

Полная специализация больше не является шаблоном. Это конкретная функция. Как таковой он должен быть (неявно или явно) объявлен inline. Проще всего добавить это ключевое слово перед спецификацией типа возврата.

Тем не менее, представленный код не соответствует вашему сообщению об ошибке.

В сообщении об ошибке говорится о типе возврата std::string, а не в типе возврата int.

Приветствия и hth.,

Ответ 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()));
}

Существует точно подобная тема/проблема, обсуждающая эту вещь. Пожалуйста, взгляните на это:

Специализация частичного шаблона для определенного типа, С++