Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как заставить C++ специализировать шаблонный класс 
V
    Опции темы
d06osipov
Дата 5.6.2008, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Есть шаблонный класс A<T> (синглетон). Есть другой класс B<T> (тоже синглетон). Мне нужно специализировать B<T> для всех типов, для которых A<T> специализирован. Напрашивается такое решение:

Код

temlate<class T>
class B:public Singleton< B<T> >
{ 
public:
  void doNothing(){}
.....
};

//Конструктор
template<class T>
A<T>::A()
{ B<T>::inst().doNothing();
}

Но это не прокатывает, так как вызов B<T>::inst() влечёт вызов конструктора B (если B ещё не создан), а конcтруктор B в свою очередь использует класс A, поэтому вызывается снова конструктор класса A (который тоже синглетон) --- второй раз для того же объекта. Но на этом не заканчивается --- A снова использует B, который не инициализирован полностью, вызывая конструктор. Получается бесконечная рекурсивная инициализация.

Напрашивается решение:
Код

temlate<class T>
class B:public Singleton< B<T> >
{ 
public:
  static void doNothing(){}
.....
};

//Конструктор
template<class T>
A<T>::A()
{ B<T>::doNothing();
}

Но это не проходит, так как компилятор, как выяснилось специализирует только статическую функцию, но не сам класс.

Ещё вариант:

Код

tempalte<class T>
void A<T>::neverCall()
{ B<T>::inst().doNothing();
}

Это не годиться, так как функция A<T>::neverCall может не специализироваться.

Я делаю так:
Код

//деструктор
template<class T>
A<T>::~A()
{ B<T>::inst().doNothing();
}

Это работает, но я опасаюсь, что класс B может удалиться раньше, чем A, а это может привести к сигфолту. 

Скажите, есть какой-нибудь Стандартный, надёжный способ?
PM MAIL   Вверх
Alek86
Дата 5.6.2008, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



не совсем понял
нужно специализировать или инстанциировать?


--------------------
user posted image    user posted image
PM MAIL   Вверх
d06osipov
Дата 5.6.2008, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Пример: у меня в программе используется класс A<int>.
Мне нужно, чтобы C++ автоматически специализировал класс B<int> в таком случае. (и это не бессмысленно: так как B<T> синглетон, его конструктор будет вызван до main(), в том случае, если этот класс вообще существует, то есть специализирован, а это мне и надо. Больше от класса B мне ничего не требуется, кроме вызова конструктора до main())

Это сообщение отредактировал(а) d06osipov - 5.6.2008, 11:40
PM MAIL   Вверх
Alek86
Дата 5.6.2008, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



если инстанцировать, то рекомендую прочесть Главу 10 книги
Вандевурд, Джосаттис - Шаблоны C++



если нету но хочется, могу подсказать, где взять - обращайся в личку

Добавлено @ 11:44
Цитата(d06osipov @  5.6.2008,  11:39 Найти цитируемый пост)
C++ автоматически специализировал класс B<int> в таком случае.

могу и ошибаться, но это, вроде, называется инстанцирование по требованию
если ошибаюсь, то глава 10 той книги тебе вряд-ли поможет smile

Добавлено @ 11:48
может, поможет
Цитата

Точку инстанцирования для специализации шаблона можно создать явным образом. 
Конструкция, с помощью которой это достигается, называется директивой явного  
инстанцирования (explicit instantiation directive). Синтаксически она состоит из ключевого 
слова template, за которым следует объявление инстанцируемой специализации. 
Код

template<typename T> 
void f(T) throw(T) 
{ 
} 
// Четыре примера корректного явного инстанцирования 
template void f<int>(int) throw(int); 
template void fo(float) throw(float); 
template void f(long) throw(long); 
template void f(char); 

 Обратите внимание, что корректна каждая из четырех приведенных выше директив 
инстанцирования. Аргументы шаблона могут быть выведены (см. главу 11, "Вывод  
аргументов шаблонов"), а спецификации исключений могут быть опущены. Если же эти 
спецификации не опущены, то они должны соответствовать заданным в шаблоне. 
Члены шаблонов классов также можно явно инстанцировать. 
Код

template<typename T> 
class S { 
public: 
void f() { 
} 
}; 
template void S<int>::f(); 
template class S<void>; 



Это сообщение отредактировал(а) Alek86 - 5.6.2008, 11:52


--------------------
user posted image    user posted image
PM MAIL   Вверх
Lazin
Дата 5.6.2008, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(d06osipov @  5.6.2008,  11:21 Найти цитируемый пост)
Это работает, но я опасаюсь, что класс B может удалиться раньше, чем A, а это может привести к сигфолту. 

а как специализация класса поможет контролировать время жизни глобальных объектов... 
PM MAIL Skype GTalk   Вверх
Alek86
Дата 5.6.2008, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Цитата(d06osipov @  5.6.2008,  11:21 Найти цитируемый пост)
 а конcтруктор B в свою очередь использует класс A, поэтому вызывается снова конструктор класса A (который тоже синглетон)

кажись, у тебя неправильно организован синглтон
у синглтона должен быть закрытый или защищенный конструктор, чтобы никто кроме него самого не мог его создать. А остальные могут получать экземпляр синглтона только через статический GetInstance


--------------------
user posted image    user posted image
PM MAIL   Вверх
d06osipov
Дата 5.6.2008, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Цитата(Alek86 @  5.6.2008,  12:45 Найти цитируемый пост)
у синглтона должен быть закрытый или защищенный конструктор, чтобы никто кроме него самого не мог его создать. А остальные могут получать экземпляр синглтона только через статический GetInstance 


Да, но в синглетонах Мейерса (какие я использую), если объект ещё не инициализирован и происходит Instance, то он создаётся, а значит вызывается конструктор. То есть конструктор неявно вызывается через функцию inst().

PM MAIL   Вверх
mes
Дата 5.6.2008, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(d06osipov @  5.6.2008,  13:13 Найти цитируемый пост)
Да, но в синглетонах Мейерса (какие я использую), если объект ещё не инициализирован и происходит Instance, то он создаётся, а значит вызывается конструктор. То есть конструктор неявно вызывается через функцию inst().

так во всех синглетонах 

вызывается только свой конструктор  - конструкторы остальных синглетонов недоступны 


--------------------
PM MAIL WWW   Вверх
Alek86
Дата 5.6.2008, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



угу...
а все же в чем задача?
к примеру это
Цитата(d06osipov @  5.6.2008,  11:39 Найти цитируемый пост)
так как B<T> синглетон, его конструктор будет вызван до main()

насколько я знаю, неправильно
если у тебя там new используется, то объект создастся во время работы inst()
если же статический объект, то ему можно вообще не создаваться, если функция inst() не будет вызвана
это называется "отложенная инициализация", кажется


--------------------
user posted image    user posted image
PM MAIL   Вверх
mes
Дата 5.6.2008, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



если у тебя один синглетон для создания своей инстанции требует инстанцию другого синглетона, которая в свою очередь требует первую - значит что то в проектировке программы не верно .. (аж язык поломался от закрутки - бедный компилятор что ему приходится читать  smile )


--------------------
PM MAIL WWW   Вверх
d06osipov
Дата 5.6.2008, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Нет. Один синглтон требует инициализации другого. Это верно. Но другой не требует инициализации первого. Он должен лишь гарантировать специализацию первого.

Добавлено через 9 минут и 3 секунды
Я использую два вида синглтонов. 
Первый вид --- такой, как в Boost::singleton. Он гарантирует инициализацию до main.
Второй --- синглетон Мейерса. Он гарантирует инициализацию при первом использовании.

Если синглтоны первого типа используют только синглтоны второго, то коллизий произойти не может (второй тип инициализируется при обращении). Такое использование мне и требуется. A<T> --- второго типа. Его объект может вообще не создаваться в процессе работы программы, но он специализирован для всех типов, которые нужны. Конструктор B<T> содержит важный код, который должен быть выполнен прежде всего, но B<T>. B<T> синглтон первого типа, поэтому его конструктор автоматически вызовется до main, но B<T> нигде не упоминается в программе, а поэтому компилятор не специализирует его.
PM MAIL   Вверх
mes
Дата 5.6.2008, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(d06osipov @  5.6.2008,  13:48 Найти цитируемый пост)
гарантировать специализацию первого. 

синглетон не гарантирует специализацию ..
или мы расходимся в трактовке понятия - нельзя ли уточнить что подразумевается с вашей точки зрения ?



--------------------
PM MAIL WWW   Вверх
d06osipov
Дата 5.6.2008, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Цитата(mes @  5.6.2008,  13:59 Найти цитируемый пост)
синглетон не гарантирует специализацию

Совершенно верно. В этом и проблема.

Пользователь пишет у себя в коде A<int>::inst(). 
Он и понятия не имеет про B<T>; и я не могу заставлять его знать про B<T>. Поэтому нигде в программе не употребляется B<int> (только A<int>), но мне надо, чтобы такой класс существовал. А если бы он существовал, то был бы синглтоном, и конструктор выполнился бы до main --- то что мне требуется (иными словами, мне надо до main() выполнить код, зависящий от T для всех типов T, для которых есть A<T>).
Я думал так: если A<T> существует, компилятор обязан специализировать два метода: конструктор и деструктор. Если, например, в конструкторе A<T> я обращусь к объекту B<T>, то значит, компилятору придётся специализировать B<T> (он используется в существующей функции). Но возникла проблема с рекурсивной инициализацией. Если поместить в деструктор --- может возникнуть проблема с обращением к уничтоженному объекту. А конструктор и деструктор это единственные два метода про которые наверняка известно, что они специализируются.

Вот я думаю, может так можно:
Код

template <class T>
class B
{ 
public:
  int doNothing();
};

<template class T>
A::A()
{ sizeof(B<T>::inst().doNothing());
}

Здесь используется тип B<T>, но ничего не вызывается. Я опасаюсь компилятор может повести себя так: "я размер узнал, больше мне этот класс не нужен, не буду специализировать".

Цитата

или мы расходимся в трактовке понятия - нельзя ли уточнить что подразумевается с вашей точки зрения


Вот что: компилятор специализирует класс A для типа T, значит в откомпилированной программе существует тип A<T>. Это означает, что существует код хотя бы для одной нестатической функции A<T>::f, выделена память для всех статических членов в сегменте. 

На первый взгляд может показаться, нет никакой разницы между специализированным классом и нет. Начинающие даже, наверное думают, что есть классы A<T> для всех типов T. Но когда в ход идут трюки с Синглетонами --- тут очень большая разница, специализирован тип, или нет.

Это сообщение отредактировал(а) d06osipov - 5.6.2008, 15:49
PM MAIL   Вверх
Alek86
Дата 5.6.2008, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Цитата(d06osipov @  5.6.2008,  15:33 Найти цитируемый пост)
но мне надо, чтобы такой класс существовал.

думаю, немногие поняли, что тебе все же нужно
я тоже не понял smile
и похоже ты до сих пор путаешь специализацию и инстанцирование

может это поможет? затайпдефить один синглтон в другом?
Код
// класс, который нужно явно инстанцировать
template<typename T> 
class S {};

template <typename T>
class C {
 typedef S<T> Dummy;
};


хотя не совсем уверен, что компилер обязан инстанцировать этот тайпдеф, если он нигде не используется

Добавлено @ 16:07
Цитата(d06osipov @  5.6.2008,  15:33 Найти цитируемый пост)
компилятор специализирует класс A для типа T

колмпилятор не специализирует, а инстанцирует
инстанциация - когда компилер встречает строчку типа C<int>, смотрит, что такого типа еще нет, и по шаблону класса C создает тип C<int>

специализация - это когда у тебя есть шаблонный класс.
Код
template <typename T>
class C {/*realization*/};

потом ты понимаешь, что для типа int можно сделать намного более удобную реализацию:
Код
template <>
class C<int> {/*realization for int*/};

вот то что ты дописал - это специализация

Это сообщение отредактировал(а) Alek86 - 5.6.2008, 16:08


--------------------
user posted image    user posted image
PM MAIL   Вверх
d06osipov
Дата 5.6.2008, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Цитата(Alek86 @ 5.6.2008,  16:01)
Цитата(d06osipov @  5.6.2008,  15:33 Найти цитируемый пост)
но мне надо, чтобы такой класс существовал.

думаю, немногие поняли, что тебе все же нужно
я тоже не понял smile
и похоже ты до сих пор путаешь специализацию и инстанцирование

может это поможет? затайпдефить один синглтон в другом?
Код
// класс, который нужно явно инстанцировать
template<typename T> 
class S {};

template <typename T>
class C {
 typedef S<T> Dummy;
};


Нет, вы правильно меня поняли. Я тоже думал, что тайпдеф прокатит, ан нет. Компилятор умный (g++), он этот тайпдеф видит, но класс не специализирует (дествительно, этот тайпдеф по идее вообще никак на объектный файл не должен влиять. Так и происходит). Я пробовал указатели на него делать, но лишнюю работу g++ на себя брать не хочет.

Это сообщение отредактировал(а) d06osipov - 5.6.2008, 16:12
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0676 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.