2016-10-11 2 views
3

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

$ кошка 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(); 
} 

Если я скомпилировать без оптимизации и запустить его, он дает:

г ++ foo_int.cpp foo_float.cpp main.cpp & & a.out
инициализации INT Foo
инициализации поплавок Foo

Если добавить оптимизацию, то результат отличается:

$ г ++ foo_int.cpp foo_f loat.cpp main.cpp -O2 & & a.out
инициализации INT Foo

Результат отличается. Некоторые объяснения из интернета сказал, что это связано с какой-то внутренний механизм «слабого символа» в ССАГПЗ реализации, но мой вопрос:

  1. Является ли «слабый символ»/«сильный символ» понятие ССАГПЗ/г ++ , или это часть спецификации языка c/C++.

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

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

+0

Объявление специализации 'void foo:: init()' не отображается в 'main' ... Ваша программа плохо сформирована. – Jarod42

+0

Будьте осторожны при форматировании текста. Только блоки кода сохраняют пробелы и разрывы строк. Когда вы вставили консольный вывод 'g ++' под разметкой '>', он проигнорировал разрывы строк, все из которых были сжаты в одну строку текста. Чтобы сохранить разрывы строк, поместите двойное пространство в конце каждой строки. Или просто вставить как блок кода. У читателей обычно нет проблем с тем, чтобы заметить, какой из них содержит код и какой из них содержит консольный дамп :) – quetzalcoatl

+0

«У меня есть заголовочный файл для класса» - нет, у вас есть заголовочный файл для ** шаблона ** , –

ответ

3

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

В модуле компиляции foo_float.cpp определено определение, а другое - в блоке компиляции main.cpp.

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

  • с оптимизацией выходных, программа генерирует фактический вызов функции, а компоновщик случилось поставить версию foo_float.cpp «ю.ш. функции в исполняемом файле.
  • С оптимизацией включен, при компиляции main.cpp компилятор ввел функцию —, естественно, это было бы встроенной версией функции main.cpp.
+0

В main.cpp: потому что нет декларации специализации' foo :: init', тогда общее считается определением для 'foo : : init'? Это причина? – bolov

3

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

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

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

+0

Да, это на самом деле больше, чем в предыдущем ответе – bolov

Смежные вопросы