Linux C ++: как правильно использовать шаблонные специализации для нескольких файлов? - PullRequest
5 голосов
/ 23 января 2012

У меня странная проблема. В Windows с Visual Studio 2010, а также с компилятором Intel все связано, как и ожидалось. Но когда я пытаюсь скомпилировать свой код с помощью CLang 3.0 в Linux, он компилируется (и если я использую только один файл CPP, он также связывает и запускает), но не связывает.

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

 template<class T> void myFunc(T in) { }
 template<> void myFunc<int>(int in) { }

Теперь из линкера Linux я бы получил что-то вроде:

"file xyz": множественное определение "myFunc (int in)", сначала определенное в "some file".

Но как бы мне это предотвратить? Так как он работает на Windows, я полагаю, что он должен работать на Linux тоже как-то?

То же самое относится и к статическим элементам данных шаблона, которые более или менее совпадают с описанными выше, только если вы объявляете переменную вместо функции. Я бы предпочел, чтобы это работало для статических членов данных шаблона.

Если все остальное не удается, я полагаю, что я все еще мог бы создать файл "MakeAll.cpp", который просто включает все имеющиеся CPP, но для меня это не звучит как желаемое решение ...

Спасибо за вашу помощь!

Ответы [ 3 ]

9 голосов
/ 23 января 2012

Насколько я понимаю, вы на самом деле определяете специализацию шаблонов несколько раз, и это также должно привести к ошибке для компиляторов Windows.

В вашем заголовочном файле вы определяете функцию, предоставляя тело:

template<> void myFunc<int>(int in) { }

Это определение будет существовать в нескольких блоках компиляции, и компоновщик должен пожаловаться.

Для вашей специализации шаблона применяются те же правила, что и для обычных не шаблонных функций: либо используйте inline, либо используйте отдельное объявление и определение, поставив

template<> void myFunc<int>(int in);

в заголовке и

template<> void myFunc<int>(int in)
{
    // ...
}

в файле .cpp.

3 голосов
/ 23 января 2012

Шаблоны создаются компилятором, и компилятор обязан убедиться, что они определены только один раз.

Когда вы полностью специализируете функцию, это больше не шаблон (а обычная функция), и ваша ответственность за обеспечение того, чтобы он не был многократно определен.

Разница между этими функциями

template<>
void f<int>(int x)
{ }

void f(int x)
{ }

очень мала, когда дело доходит доодно определение правила.

Добавление inline помогает в обоих случаях.

0 голосов
/ 23 января 2012

У меня сейчас нет стандарта, но я думаю, что специализация должна быть объявлена ​​inline.

...