множественное определение специализации шаблона при использовании различных объектов
когда я использую специализированный шаблон в разных объектных файлах, я получаю ошибку "множественного определения" при связывании. Единственное решение, которое я нашел, включает в себя использование "встроенной" функции, но это просто кажется некоторым обходным путем. Как решить эту проблему без использования ключевого слова "inline"? Если это невозможно, то почему?
вот пример код:
paulo@aeris:~/teste/cpp/redef$ cat hello.h
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
template <class T>
class Hello
{
public:
void print_hello(T var);
};
template <class T>
void Hello<T>::print_hello(T var)
{
std::cout << "Hello generic function " << var << "n";
}
template <> //inline
void Hello<int>::print_hello(int var)
{
std::cout << "Hello specialized function " << var << "n";
}
#endif
paulo@aeris:~/teste/cpp/redef$ cat other.h
#include <iostream>
void other_func();
paulo@aeris:~/teste/cpp/redef$ cat other.c
#include "other.h"
#include "hello.h"
void other_func()
{
Hello<char> hc;
Hello<int> hi;
hc.print_hello('a');
hi.print_hello(1);
}
paulo@aeris:~/teste/cpp/redef$ cat main.c
#include "hello.h"
#include "other.h"
int main()
{
Hello<char> hc;
Hello<int> hi;
hc.print_hello('a');
hi.print_hello(1);
other_func();
return 0;
}
paulo@aeris:~/teste/cpp/redef$ cat Makefile
all:
g++ -c other.c -o other.o -Wall -Wextra
g++ main.c other.o -o main -Wall -Wextra
и наконец:
paulo@aeris:~/teste/cpp/redef$ make
g++ -c other.c -o other.o -Wall -Wextra
g++ main.c other.o -o main -Wall -Wextra
other.o: In function `Hello<int>::print_hello(int)':
other.c:(.text+0x0): multiple definition of `Hello<int>::print_hello(int)'
/tmp/cc0dZS9l.o:main.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: ** [all] Erro 1
если я раскомментирую "встроенный" внутри hello.h, код будет компилироваться и выполняться, но это просто кажется мне каким-то "обходным путем": что делать, если специализированная функция большая и используется много раз? Получу ли я большой двоичный файл? Есть ли другой способ сделать это? Если да, то как? Если нет, то почему?
Я пытался искать ответы, но все, что я получил был "использовать inline" без каких-либо дополнительных объяснений.
спасибо
3 ответа:
интуитивно, когда вы полностью специализируетесь на чем-то, это больше не зависит от параметра шаблона-поэтому, если вы не сделаете специализацию встроенной, вам нужно поместить ее в a .cpp файл вместо a .ч или вы в конечном итоге нарушает правило одного определения, как говорит Дэвид. Обратите внимание, что при частичной специализации шаблонов частичные специализации по-прежнему зависят от одного или нескольких параметров шаблона, поэтому они по-прежнему входят в a .H-файл.
ключевое слово
inline
больше о том, чтобы сообщить компилятору, что символ будет присутствовать в более чем одном объектном файле без нарушения правила одного определения, чем о фактическом встраивании, которое компилятор может решить делать или не делать.проблема, которую вы видите, заключается в том, что без встроенного, функция будет скомпилирована во всех единицах перевода, которые включают заголовок, нарушая ODR. Добавление
inline
есть правильный путь. В противном случае можно переслать объявление специализацию и обеспечить ее в едином блоке перевода, как вы бы сделали с любой другой функцией.