Вы не можете пересылать объявления "частей" таких классов. Даже если бы вы могли, вам все равно нужно было бы где-то создать экземпляр кода, чтобы вы могли ссылаться на него. Есть способы справиться с этим, вы можете создать небольшую библиотеку с экземплярами общих контейнеров (например, vector) и связать их. Тогда вам нужно будет только скомпилировать, например. вектор один раз. Чтобы реализовать это, вам нужно будет использовать что-то вроде -fno-implicit-templates
, по крайней мере, предполагая, что вы придерживаетесь g ++ и явно создаете экземпляр шаблона в вашей библиотеке с помощью template class std::vector<int>
Итак, настоящий рабочий пример. Здесь у меня есть 2 файла, a.cpp и b.cpp
a.cpp:
#include <vector> // still need to know the interface
#include <cstdlib>
int main(int argc, char **argv) {
std::vector<int>* vec = new std::vector<int>();
vec->push_back(3);
delete vec;
return EXIT_SUCCESS;
}
Так что теперь я могу скомпилировать a.cpp с -fno-implicit-templates
:
g++ -fno-implicit-templates -c a.cpp
Это даст мне о.о. Если я тогда пытаюсь связать, я получаю:
g++ a.o
/usr/bin/ld: Undefined symbols:
std::vector<int, std::allocator<int> >::_M_insert_aux(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&)
void std::_Destroy<int*, std::allocator<int> >(int*, int*, std::allocator<int>)
collect2: ld returned 1 exit status
Ничего хорошего. Итак, мы переходим к b.cpp:
#include <vector>
template class std::vector<int>;
template void std::_Destroy(int*,int*, std::allocator<int>);
template void std::__uninitialized_fill_n_a(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, unsigned long, int const&, std::allocator<int>);
template void std::__uninitialized_fill_n_a(int*, unsigned long, int const&, std::allocator<int>);
template void std::fill(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&);
template __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > std::fill_n(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, unsigned long, int const&);
template int* std::fill_n(int*, unsigned long, int const&);
template void std::_Destroy(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, std::allocator<int>);
Теперь вы говорите себе, откуда взялись все эти дополнительные шаблоны? Я вижу template class std::vector<int>
, и это нормально, но как насчет остального? Короче говоря, короткий ответ заключается в том, что эти вещи по необходимости немного запутаны, и когда вы создаете их вручную, из-за этого некоторые из этих запутанностей просачиваются. Вы, наверное, удивляетесь, как я понял, что мне нужно для создания экземпляра. Ну я использовал ошибки компоновщика;).
Итак, теперь мы компилируем b.cpp
g++ -fno-implicit-templates -c b.cpp
И мы получаем Связав а.о и б.о мы можем получить
g++ a.o b.o
Ура, нет ошибок компоновщика.
Итак, чтобы получить некоторые подробности о вашем обновленном вопросе, если это класс домашнего приготовления, он не обязательно должен быть таким грязным. Например, вы можете отделить интерфейс от реализации, например, скажем, у нас есть c.h, c.cpp, в дополнение к a.cpp и b.cpp
c.h
template<typename T>
class MyExample {
T m_t;
MyExample(const T& t);
T get();
void set(const T& t);
};
c.cpp
template<typename T>
MyExample<T>::MyExample(const T& t) : m_t(t) {}
template<typename T>
T MyExample<T>::get() { return m_t; }
template<typename T>
void MyExample<T>::set(const T& t) { m_t = t; }
a.cpp
#include "c.h" // only need interface
#include <iostream>
int main() {
MyExample<int> x(10);
std::cout << x.get() << std::endl;
x.set( 9 );
std::cout << x.get() << std::endl;
return EXIT_SUCCESS;
}
b.cpp, «библиотека»:
#include "c.h" // need interface
#include "c.cpp" // need implementation to actually instantiate it
template class MyExample<int>;
Теперь вы компилируете b.cpp в bo один раз. Когда a.cpp изменится, вам просто нужно перекомпилировать это и связать в b.o.