если в заголовочнике прописать экстерном шаблонное определение
//header.htemplate <typename Arg> class Ft {
public:
typedef std::vector<Arg> VectorT;
static VectorT p_;
};
template <class Arg> externtypename Ft<Arg>::VectorT Ft<Arg>::p_;
, то всё прекрасно начинает работать.
При этом если не определять VectorT, а прописывать напрямую std::vector<Arg>, то всё работает совсем по другому и компилер начинает ругаться и на extern-объявление, и на обычное, а без них выдаёт вообще undefined reference и как это скомпилить — вообще не понятно.
Помогите достичь просветления.
Re: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, Molchalnik, Вы писали:
M>Помогите достичь просветления.
Не ищи сложных путей,
не создавай трудности линкеру, с тем, чтобы потом их героически преодолевать,
не нарушай ODR (в первом случае ты создаёшь предпосылку: объявляешь vector<Arg> Ft<Arg>::p_, а определяешь vector<int> Ft<Arg>::p_).
Определение шаблона должно быть доступно всем.
И все, кому оно нужно, спровоцируют воплощения, а линкер сам разберётся, как избавиться от дубликатов — так же, как он избавляется от дубликатов инлайн-функций.
Перекуём баги на фичи!
Re[2]: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Molchalnik, Вы писали:
M>>Помогите достичь просветления.
К>Не ищи сложных путей, К>не создавай трудности линкеру, с тем, чтобы потом их героически преодолевать, К>не нарушай ODR (в первом случае ты создаёшь предпосылку: объявляешь vector<Arg> Ft<Arg>::p_, а определяешь vector<int> Ft<Arg>::p_).
Так я бы и рад вообще оставить одно определение — которое внутри определения класса, так ведь не работает же!!! пишет — "undefined reference"!!!
Я вообще в шоке.
Re[3]: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, Molchalnik, Вы писали:
M>Здравствуйте, Кодт, Вы писали:
К>>Здравствуйте, Molchalnik, Вы писали:
M>>>Помогите достичь просветления.
К>>Не ищи сложных путей, К>>не создавай трудности линкеру, с тем, чтобы потом их героически преодолевать, К>>не нарушай ODR (в первом случае ты создаёшь предпосылку: объявляешь vector<Arg> Ft<Arg>::p_, а определяешь vector<int> Ft<Arg>::p_).
M>Так я бы и рад вообще оставить одно определение — которое внутри определения класса, так ведь не работает же!!! пишет — "undefined reference"!!! M>Я вообще в шоке.
определи статического члена для специализации в cpp файле:
template<> vector<int> Ft<int>::_p;
и все ьудет нормально.
Re[4]: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, Molchalnik, Вы писали:
M>Здравствуйте, Кодт, Вы писали:
К>>Здравствуйте, Molchalnik, Вы писали:
M>>>Помогите достичь просветления.
К>>Не ищи сложных путей, К>>не создавай трудности линкеру, с тем, чтобы потом их героически преодолевать, К>>не нарушай ODR (в первом случае ты создаёшь предпосылку: объявляешь vector<Arg> Ft<Arg>::p_, а определяешь vector<int> Ft<Arg>::p_).
M>Так я бы и рад вообще оставить одно определение — которое внутри определения класса, так ведь не работает же!!! пишет — "undefined reference"!!! M>Я вообще в шоке.
еще одна опция — оставить
template<typename T> vector<T> Ft<T>:_p
в хидере, но нигде не пользоваться explicit specialization для шаблона Ft (те не писать нигде
template class Ft<int>;
), а то порушишь ODR.
Re[5]: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, andyp, Вы писали:
M>>если обращение к Ft<int> есть в обоих cpp файлов???
A>так делать не надо совсем. Может оказаться так, что обратишься к p_ до вызова его конструктора.
?? т.е. шаблон со статическим членом нельзя использовать в двух cpp? Странно
Re[7]: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, Molchalnik, Вы писали:
M>?? т.е. шаблон со статическим членом нельзя использовать в двух cpp? Странно
Шаблон не при делах. Попробуй поиспользовать значение глобальной переменной в глобальной переменной из другой единицы трансляции. Стандарт не специфицирует порядок инициалиации в таких случаях.
Re[8]: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, andyp, Вы писали:
A>Здравствуйте, Molchalnik, Вы писали:
M>>?? т.е. шаблон со статическим членом нельзя использовать в двух cpp? Странно
A>Шаблон не при делах. Попробуй поиспользовать значение глобальной переменной в глобальной переменной из другой единицы трансляции. Стандарт не специфицирует порядок инициалиации в таких случаях.
но глобальную переменную можно объявить как extern
Re[3]: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, Molchalnik, Вы писали:
M>Так я бы и рад вообще оставить одно определение — которое внутри определения класса, так ведь не работает же!!! пишет — "undefined reference"!!! M>Я вообще в шоке.
Внутри класса не определение, а объявление статического члена-данного.
Определение вовне, так же, как в нешаблонном классе.
Только слово extern не нужно.
template<class T>
struct Foo
{
typedef vector<T> U;
static U x;
static int y;
static const U cx;
static const int cy = 123; // интегральные константы можно определять на месте
// предвосхищая ещё вопросы по шаблонам...void bar();
template<class Z> void buz();
};
template<class T> typename Foo<T>::U Foo<T>::x; // с дефолтным конструкторомtemplate<class T> int Foo<T>::y = 42; // инициализация присваиванием (конструктор копирования)template<class T> typename Foo<T>::U const Foo<T>::cx (10); // с недефолтным конструкторомtemplate<class T> void Foo<T>::bar() {}
template<class T> template<class Z> void Foo<T>::buz() {}
Перекуём баги на фичи!
Re[9]: Ещё один вопрос про определение статического члена шаблонного класса
К>template<class T> typename Foo<T>::U Foo<T>::x; // с дефолтным конструктором
К>
Кодт, тут тонкость одна есть — обязательно нужно равно после х. Иначе компилятор не сможет различить объявление от определения (поправьте, если не прав) и будет как раз undefined reference.
Re[2]: Ещё один вопрос про определение статического члена шаблонного класса
BFE>А зачем тут extern? Без него всё должно работать.
Вот и я думаю — а зачем здесь extern? и без него должно работать
M>>Помогите достичь просветления.
BFE>Что не ясно-то?
почему не работает без extern, почему не работает с объявлением статического члена в cpp, если ссылка на инстанцию шаблона есть в другом cpp
Хотя должно вроде работать, вот и Кодт написал, однако же...
Re[5]: Ещё один вопрос про определение статического члена шаблонного класса
К>>template<class T> typename Foo<T>::U Foo<T>::x; // с дефолтным конструктором
К>>
A>Кодт, тут тонкость одна есть — обязательно нужно равно после х. Иначе компилятор не сможет различить объявление от определения (поправьте, если не прав) и будет как раз undefined reference.
Не прав. Тут же имя класса участвует, таких объявлений не бывает.
class A{};
int A::a; // это не объявление, а ошибка компиляции
Re[6]: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, enji, Вы писали:
E>Здравствуйте, andyp, Вы писали:
К>>>
К>>>template<class T> typename Foo<T>::U Foo<T>::x; // с дефолтным конструктором
К>>>
A>>Кодт, тут тонкость одна есть — обязательно нужно равно после х. Иначе компилятор не сможет различить объявление от определения (поправьте, если не прав) и будет как раз undefined reference.
E>Не прав. Тут же имя класса участвует, таких объявлений не бывает.
E>
E>class A{};
E>int A::a; // это не объявление, а ошибка компиляции
E>
Re[6]: Ещё один вопрос про определение статического члена шаблонного класса
Здравствуйте, enji, Вы писали:
E>Здравствуйте, andyp, Вы писали:
К>>>
К>>>template<class T> typename Foo<T>::U Foo<T>::x; // с дефолтным конструктором
К>>>
A>>Кодт, тут тонкость одна есть — обязательно нужно равно после х. Иначе компилятор не сможет различить объявление от определения (поправьте, если не прав) и будет как раз undefined reference.
E>Не прав. Тут же имя класса участвует, таких объявлений не бывает.
E>
E>class A{};
E>int A::a; // это не объявление, а ошибка компиляции
E>
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Molchalnik, Вы писали:
К>Внутри класса не определение, а объявление статического члена-данного. К>Определение вовне, так же, как в нешаблонном классе. К>Только слово extern не нужно.
Кодт, то, что ты написал в примере, красиво и понятно, я это знаю и так и делаю. Так ведь не работает же! Должно работать в теории, но не работает. Точнее, работает, пока cpp файл один. Как только начинаешь обращаться к инстанции шаблонного класса из двух cpp (или даже из одного, но не того, в котором дано определение статического члена-данного шаблонного класса), начинается разнообразная хрень. Написали здесь много чего, но ответа на свой вопрос я так не получил. У меня gcc 4.7.2 для убунты, возможно, это фишка или баг gcc
Я работаю с шаблонами многие годы, пишу иногда очень сложные вещи, но такое — впервые. Я не считаю себя гуру, т.к. знаю C++ по книгам, а не по заученным пунктам стандарта (а без этого, в моём понимании, гуру не гуру), но для своих коллег я вполне сойду за гуру, если речь пойдёт о шаблонах. И тем не менее, в чём-то простом и известном и понятном для меня у меня выходит чёрти что. Значит, у меня либо пробел в понимании, либо я где-то очень глупо и по-дурацки протупил, либо это баг gcc. В любом случае буду рад помощи.
Опять же, отсутствие глубокого знания стандарта в наше время, когда компиляторы приближаются к стандарту всё больше и больше, становится фатальным багом — то, что работало раньше из-за низкой совместимости с C++98 standard теперь не работает из-за высокой совместимости с c++11 standard