templates + static data + DLLs
От: Sergeem Израиль  
Дата: 29.12.02 18:24
Оценка:
Не знаю, правильно ли я попал, ибо эти
проблемы связаны сугубо с wndows dll и
VC 6.0.

Словом, имеются следующие классы
(все сильно утрировано ) :

struct Mummy
{
    Mummy() {puts("mummy ctor");}
    ~Mummy() {puts("mummy dtor");}
};


template <class C>
struct Templ
{
    static int *foo();
private:
    static int i;
};

template <class C>
int *Templ<C>::foo() 
{
    static Mummy mum;
    return &i;
}

template <class C>
int Templ<C>::i = 0;


Все юзают Templ из разных dll-ек, ожидая получить
один и тот же результат ф-ции foo, которая возвращает
адрес статического члена класса, для одних и тех же
instantiations (как бы это по русски?) класса Templ<C>.
Все бы хорошо, но когда выбираем опцию вставки
inline-функций в код, то это не работает. Очевидно,
экземпляр Templ<TheClass>::i вставляется в каждую dll.

Чтобы пофиксить такой непорядок, я экспортирую
instantiations шаблона Templ<C> для конкретных
классов С, которые у меня используются. Т.е.
экземпляр Templ<TheClass>::i теперь находится
в TheClass.dll, и все с радостью его юзают.
Типа так:

TheClass.h :  extern template struct THECLASSDLL_API ::Templ<TheClass>;

TheClass.cpp: int Templ<TheClass>::i = 0;


Первая проблема: таких классов TheClass довольно много,
и нужно перелопатить кучу кода, да и к тому же это дело
надо окружать #ifdef-ом, потому как это ms-specific
extension, а код — multi-platform.

Вторая проблема: тело функции foo надо вставлять внутрь
класса Templ, иначе не компилируется. Это не очень
желательно, поскольку foo довольно больших размеров.

Третья проблема: не вызывается конструктор Mummy!!???
Пофиксино путем переноса mum в члены класса Templ.

Спрашивается — есть ли какие-то обходные маневры для
решения этих проблем.

ЗЫ. Спасибо, если дочитали до конца
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
Re: templates + static data + DLLs
От: Bell Россия  
Дата: 30.12.02 07:37
Оценка:
Здравствуйте, Sergeem, Вы писали:

Попробуй так:


template <class C>
struct Templ
{
#pragma auto_inline (off)
   static int *foo();
#pragma auto_inline (on)
private:
   static int i;
};
Любите книгу — источник знаний (с) М.Горький
Re[2]: templates + static data + DLLs
От: Sergeem Израиль  
Дата: 30.12.02 08:43
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, Sergeem, Вы писали:


B>Попробуй так:


B>

B>
B>template <class C>
B>struct Templ
B>{
B>#pragma auto_inline (off)
B>   static int *foo();
B>#pragma auto_inline (on)
B>private:
B>   static int i;
B>};
B>


B>


не помогает!
Templ::i все равно размножается!
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
Re: templates + static data + DLLs
От: desperado_gmbh http://www.livejournal.com/users/tolstopuz
Дата: 30.12.02 09:50
Оценка:
Здравствуйте, Sergeem, Вы писали:

S>template <class C>

S>int *Templ<C>::foo()
S>{
S> static Mummy mum;
S> return &i;
S>}
S>Все бы хорошо, но когда выбираем опцию вставки
S>inline-функций в код, то это не работает. Очевидно,
S>экземпляр Templ<TheClass>::i вставляется в каждую dll.

Глюк vc6. Я копался в сгенерированном коде — компилятор путает скрытые флажки, показывающие, что статический объект уже создан. Проще всего исправить через int foo(...).
Re: templates + static data + DLLs
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 04.01.03 12:02
Оценка:
Здравствуйте, Sergeem, Вы писали:

Ну, есть мысль. Код можно менять? Тогда избавься от этих переменных. Исползуй "синглтон Мейерса" — доступ к статической переменной класса через его же статическую функцию. Это должно помочь решить проблему 1 без каких-либо телодвижений вообще:
template <class C>
struct Templ
{
  ...
private:
  static int& GetI() { static i = 0; return i; }
};


Проблема вторая:
Тело функции-члена foo не надо вставлять внутрь определения класса, если только это не функция-шаблон. Её внешний вид будет следующим:
template <class C>
int* Templ<C>::foo() 
{
  ...
  return &/*Templ<C>::*/GetI();
}


S>Третья проблема: не вызывается конструктор Mummy!!???

В "утрированном" коде объект не используется, и, вероятно, выкидывается. Нужно его использовать. Например, попросить его адрес:
  static Mummy mum, *pmum = &mum;
Алексей Кирдин
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.