Прежде всего, у меня есть заголовочный файл для класса, объявление специализации без определения (примеры кода из Интернета)
$ cat foo.h
template<typename T>
class foo{
public:
static void init(){
return;
}
};
template<> void foo<int>::init();
Тогда есть 2 файла реализации для специализации шаблона
$ cat foo_int.cpp
#include "foo.h"#include<stdio.h>
template<>
void foo<int>::init(){
printf("init int foo\n");
}
$ cat foo_float.cpp
#include "foo.h"#include<stdio.h>
template<>
void foo<float>::init(){
printf("init float foo\n");
}
Наконец я получил основной файл
$ cat main.cpp
#include "foo.h"
int main(){
foo<int>::init();
foo<float>::init();
}
Если я скомпилирую его без оптимизации и запустлю, это даст:
g ++ foo_int.cpp foo_float.cpp main.cpp && a.out
init int foo
init float foo
Если я добавлю оптимизацию, то результат будет другим:
$ g ++ foo_int.cpp foo_float.cpp main.cpp -O2 && a.out
init int foo
Результат другой. В некоторых объяснениях из Интернета говорится, что это связано с каким-то внутренним механизмом «слабого символа» в реализации gcc, но мой вопрос:
Является ли «слабый символ» / «сильный символ» концепцией gcc / g ++ или является частью спецификации языка c / c ++.
Если результаты отладки и выпуска отличаются, должен ли я сказать, что это ошибка / проблема в gcc / g ++, в связи с механизмом «слабого символа»? Как разработчик, я не ожидал бы, что моя отладочная версия будет вести себя иначе, чем релизная версия.
Я попробовал лязг, к сожалению, такая же ошибка. Является ли это «приемлемым» случаем для C / C ++, когда отладка / выпуск «должны» вести себя так по-разному?
Вы нарушили одно определение правила — ваша программа содержит два определения foo<float>::init
,
Одно определение происходит в модуле компиляции foo_float.cpp
, а другой появляется в модуле компиляции main.cpp
,
Нарушение одного правила определения означает неопределенное поведение — в этом случае, скорее всего, произойдет следующее:
foo_float.cpp
версия функции в исполняемом файле.main.cpp
компилятор встроил функцию — естественно, она была бы встроенной main.cpp
версия функции.Определение языка требует, чтобы вы объявили явную специализацию перед его использованием:
Если шаблон, шаблон элемента или элемент шаблона класса
в этом случае специализация должна быть объявлена
до первого использования этой специализации, что вызвало бы
неявное создание экземпляра в каждой единице перевода в
какое такое использование происходит; Диагностика не требуется. [Temp.expl.spec] / 6.
Нет декларации о явной специализации foo<float>::init()
в точке, откуда он вызывается main
, но есть явная специализация foo_float.cpp
, поэтому поведение программы не определено.