Re: Шаблон класса и DLL
От: Erop Россия  
Дата: 21.01.09 19:07
Оценка: 3 (1)
Здравствуйте, Аноним, Вы писали:

А>Это можно как-нибудь исправить?


В общем случае нельзя, так как в A не знают полный список типов, с которыми будет использовать этот код B.

но в данном конкретном случае есть выход -- можно завести какую-то runtime генерилку id.

Скажем такую:
int id_for_raw_name( const std::string& raw_name )  // это экспортируем
{
    static std::map<std::string, int> ids;
    return ids[raw_name]++;
}

// а это, в хедере
template<typename T>
struct TypeId { static int Get() { return id_for_raw_name( typeid( T ).raw_name() ); } };
Или как-то так, с точностью до синтаксиса и идентификаторов
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Шаблон класса и DLL
От: rg45 СССР  
Дата: 21.01.09 14:58
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Имеется DLL A и использующая ее DLL B. В DLL A помимо прочих экспортируемых классов и функций в одном из заголовочных файлов определен шаблон класса следующего вида (несущественные части кода опущены):

А>...
А>Классы, инстанцированные из этого шаблона, используются как в DLL A, так и в DLL B. Возникает проблема в том, что локальная статическая переменная nId, определенная в CSomeTemplate<T>::GetId(), существует в двух экземплярах (по одному в каждой из DLL) для одного и того же инстанцированного класса. Отсюда нарушение логики работы и появление багов. Это можно как-нибудь исправить?

Тут существенно не то, что эти классы являются шаблонными — та же проблема будет и с нешаблонными классами, если их не определить как экспортируемо-импортируемые.

Для того, чтоб шаблонные классы сделать экспортируемыми, в заголовочном файле нужно оставить только определение самомго шаблонного класса, а определение его функций-членов и членов-данных убрать из заголовочного файла в CPP-файл(ы), и обязательно выполнить явные инстанцирования для всех типов-параметров, с которыми предполагается данный шаблон экспортировать. Для обеспечения же экспорта-импорта можно применить распространенный прием с __declspec(export/import) + соответствующие макросы, если речь о MSVC.
--
Справедливость выше закона. А человечность выше справедливости.
Шаблон класса и DLL
От: Аноним  
Дата: 21.01.09 13:52
Оценка:
Имеется DLL A и использующая ее DLL B. В DLL A помимо прочих экспортируемых классов и функций в одном из заголовочных файлов определен шаблон класса следующего вида (несущественные части кода опущены):
template<class T>
class CSomeTemplate
{
    // ....

public:
    static int GetId()
    {
        static int nId = 0;
        if (0 == nId)
        {
            nId = GenerateUniqueId();
        }

        return nId;
    }

    // ...
};

Классы, инстанцированные из этого шаблона, используются как в DLL A, так и в DLL B. Возникает проблема в том, что локальная статическая переменная nId, определенная в CSomeTemplate<T>::GetId(), существует в двух экземплярах (по одному в каждой из DLL) для одного и того же инстанцированного класса. Отсюда нарушение логики работы и появление багов. Это можно как-нибудь исправить?
Заранее спасибо.
Re[2]: Шаблон класса и DLL
От: Аноним  
Дата: 22.01.09 14:19
Оценка:
Здравствуйте, Erop, Вы писали:

E>В общем случае нельзя, так как в A не знают полный список типов, с которыми будет использовать этот код B.


E>но в данном конкретном случае есть выход -- можно завести какую-то runtime генерилку id.


E>Скажем такую:
E>int id_for_raw_name( const std::string& raw_name )  // это экспортируем
E>{
E>    static std::map<std::string, int> ids;
E>    return ids[raw_name]++;
E>}

E>// а это, в хедере
E>template<typename T>
E>struct TypeId { static int Get() { return id_for_raw_name( typeid( T ).raw_name() ); } };
E>
Или как-то так, с точностью до синтаксиса и идентификаторов


Спасибо за идею. Вроде понял Вопрос только по генерилке — в приведенной реализации она при каждом вызове увеличивает id, назначенный тому или иному типу, в то время, как должна возвращать одно и то же значение, назначенное при первом вызове для данного типа. Ну, впрочем, это уже детали реализации, главное, идея.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.