Я не разбирался в тонкостях шаблонов, поэтому просто знаю достаточно, чтобы быть опасным. Однако я столкнулся с проблемой (о которой сообщил один из наших тестеров), когда код правильно скомпилировался в Xcode (Clang) и Visual Studio 2019, но поведение было другим, и мне интересно, какой из них был «правильным»
Рассмотрим следующий простой класс:
template <class T>
class foo
{
void set(int index, T value);
};
Этот шаблонный метод по умолчанию set отлично работал для большинства значений типа T , но мне нужно было специализировать поведение для конкретного типа, назовите его String.
Итак, в связанный файл CPP я добавил следующее:
template <>
void foo<String>::set(int index, String value)
{
// code here
};
В Xcode это сработало отлично. Вызов set со вторым параметром String правильно вызвал этот специализированный шаблон.
Однако тот же самый код, скомпилированный с помощью Visual Studio, не прошел, вёл себя по-другому. Тот же самый вызов с параметром String просто вызвал исходный set , а не специализированную версию.
Я предполагаю, что в Xcode компилятор правильно создал вызов с подписью, которая соответствует специализированной версии, которая была доступна в файле CPP и, следовательно, была правильно связана.
Итак, мои вопросы:
- Почему это работает в Xcode но не в Visual Studio
- Какой компилятор вёл себя правильно и следует ли считать проблему ошибкой в другом компиляторе?
Между прочим, я попытался создать явную подпись в файле заголовка :
template<>
void foo<String>::set(int index, String value );
и Xcode не жаловались на это, и все по-прежнему работало. Однако Visual Studio, хотя и не жаловался на эту подпись заголовка, пожаловалась во время компоновки, что не может найти подходящую реализацию, и поэтому:
Почему это не сработало?
Хотя я нашел способ сделать это, которое сработало для обоих компиляторов (по сути, вставив встроенные версии в файл заголовка, мне бы очень хотелось понять, почему это возникла проблема.
Я заранее благодарю людей.
Edit: bllow - это реальный пример, который я только что собрал. Он компилируется и отлично работает под Xcode (в частности, специализация строк правильно вызывается для переменной g), но не удается связать в Visual Studio 2019 со следующей ошибкой
(publi c: void __cdecl Foo > :: print (int, класс std :: basic_string ) "(? print @? $Foo@V?$basic_string@DU?$char_traits@D@std@@V? $allocator@D@2@@std@@@@QEAAXHV? $basic_string@DU?$char_traits@D@std@@V? $allocator@D@2@@std@@@Z) указано в функции main) указано в функции main)
Classes.h
---------
#pragma once
#include <iostream>
#include <string>
template <class T>
class Foo
{
public:
void print(int index, T value)
{
std::cout << "Using implicit template\n";
}
};
Classes.cpp
-----------
#include "Classes.h"
template<>
void Foo<std::string>::print(int i, std::string xyz)
{
std::cout << "Using explicit String template\n";
}
Main.cpp
--------
#include <string>
#include <iostream>
#include "Sub/Classes.h"
//==============================================================================
int main (int argc, char* argv[])
{
Foo<double> f;
f.print(1, 2.0);
Foo<std::string> g;
g.print(1, "abc");
return 0;
}