Моя специализация шаблона отличается отладочной версией от версии выпуска, это ошибка gcc?

Прежде всего, у меня есть заголовочный файл для класса, объявление специализации без определения (примеры кода из Интернета)

$ 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, но мой вопрос:

  1. Является ли «слабый символ» / «сильный символ» концепцией gcc / g ++ или является частью спецификации языка c / c ++.

  2. Если результаты отладки и выпуска отличаются, должен ли я сказать, что это ошибка / проблема в gcc / g ++, в связи с механизмом «слабого символа»? Как разработчик, я не ожидал бы, что моя отладочная версия будет вести себя иначе, чем релизная версия.

Я попробовал лязг, к сожалению, такая же ошибка. Является ли это «приемлемым» случаем для C / C ++, когда отладка / выпуск «должны» вести себя так по-разному?

3

Решение

Вы нарушили одно определение правила — ваша программа содержит два определения foo<float>::init,

Одно определение происходит в модуле компиляции foo_float.cpp, а другой появляется в модуле компиляции main.cpp,

Нарушение одного правила определения означает неопределенное поведение — в этом случае, скорее всего, произойдет следующее:

  • С выключенными оптимизациями программа генерирует фактический вызов функции, и компоновщик поставил foo_float.cppверсия функции в исполняемом файле.
  • С оптимизацией при компиляции main.cpp компилятор встроил функцию — естественно, она была бы встроенной main.cppверсия функции.
3

Другие решения

Определение языка требует, чтобы вы объявили явную специализацию перед его использованием:

Если шаблон, шаблон элемента или элемент шаблона класса
в этом случае специализация должна быть объявлена
до первого использования этой специализации, что вызвало бы
неявное создание экземпляра в каждой единице перевода в
какое такое использование происходит; Диагностика не требуется. [Temp.expl.spec] / 6.

Нет декларации о явной специализации foo<float>::init() в точке, откуда он вызывается main, но есть явная специализация foo_float.cpp, поэтому поведение программы не определено.

3

По вопросам рекламы [email protected]