шаблон специализации многократно определенных символов - PullRequest
20 голосов
/ 15 декабря 2010

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

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 ]

30 голосов
/ 15 декабря 2010

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

При этом указанный код не соответствует вашему сообщению об ошибке.

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

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

28 голосов
/ 15 декабря 2010

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

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

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

Я такжеЯ думал, что по определению шаблонное определение также должно быть явно inline (я всегда так делал), но не слишком удивился бы, если бы данный компилятор был слаб в применении ODR для шаблонов.Мне было бы интересно увидеть стандартную ссылку, в которой указано иное.

3 голосов
/ 15 декабря 2010

Я бы предложил вам полностью удалить следующую реализацию из вашего кода, , чтобы компилятор мог генерировать ошибку во время компиляции, если 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()));
}

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

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

...