crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )


  Ответ в Упреждающее объявление (forward declaration) для шаблонных классов
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
igor_bogomolov Дата 31.10.2010, 14:09
 
Цитата(daorus @ 31.10.2010, 13:47) *
Но почему-то у меня нет кнопки правка сообщений
Появится после 20 сообщений.

Цитата(daorus @ 31.10.2010, 13:47) *
Если я правильно понял, это вы уже не про хедеры, а про форварды в *.cpp файлах?
Это я про разделение объявления шаблонного класса и его реализации по .cpp/.h фалам http://www.cppreference.com/wiki/keywords/export (если конечно я правильно идею понял, попробовать, как вы понимаете, это не получится)

Цитата
Привык я форвары в хедерах юзать вместо инклудов. :-)
Аналогично. Если в классе объявленны только ссылки и указатели, не вижу ни какого смысла делать инклуд, только форвард объявление :)
Алексей1153 Дата 31.10.2010, 13:50
 
Цитата(daorus @ 31.10.2010, 16:41) *
Привык я форвары в хедерах юзать вместо инклудов. :-)

это не должно быть самоцелью. Частенько в этом нет необходимости, но ведёт к затратам времени на разработку плюс учитывание ручного управления памятью. Причины использовать форвард - это кросс-ссылка или большой объём кода. Других причин не вижу ))
daorus Дата 31.10.2010, 13:47
 
Цитата(Iron Bug @ 31.10.2010, 14:08) *
достигается вставкой инклюда в одном месте кода
У меня почему-то активное использование форвардов существенно экономит время компиляции. + если зависимость от форварда, то изменение в заголовочном файле не генерит флаг на перекомпиляцию. А вообще это просто вопрос привычки. Привык я форвары в хедерах юзать вместо инклудов. :-)
Цитата(Iron Bug @ 31.10.2010, 14:08) *
всё объясняется проще: когда мелкософтовский компилер
а я на g++ работаю. Про msvc вообще ничего не знаю.
Цитата(igor_bogomolov @ 31.10.2010, 15:13) *
Тут ошибка, должно быть template<class, class> class b;
Да, конечно. Я слишком увлекся идеей. Но почему-то у меня нет кнопки правка сообщений, поэтому баг так и останется висеть в моем посте. :-(

Цитата(igor_bogomolov @ 31.10.2010, 15:34) *
с использованием ключевого слова export

Если я правильно понял, это вы уже не про хедеры, а про форварды в *.cpp файлах?
т.е. типа такого
// my.cpp
export template<class, class> class B;
my::my() { B<int, int> b; }

Вы это имели ввиду?
igor_bogomolov Дата 31.10.2010, 13:34
 
Цитата(Iron Bug @ 31.10.2010, 11:08) *
с MSVC, то нельзя выносить реализацию шаблонного класса из его объявления (это баг MSVC, несовместимость со стандартами). то есть, в заголовочнике должен быть весь класс
Цитата(Алексей1153 @ 31.10.2010, 11:34) *
так и оставил в заголовочнике весь шаблон
При чем здесь MSVC? Разделить реализацию и объявление шаблона можно только с использованием ключевого слова export, которое ни один компилятор так и не реализовал. Поэтому для шаблонов подходит только модель включения, т.е. в одном файле должны быть все объявления и определения шаблона. У Вандевурда & Джосатиса это хорошо описано.

Цитата(daorus @ 31.10.2010, 11:55) *
template<class, class> b; // шаблонный форвард
Тут ошибка, должно быть template<class, class> class b;

Кстати, по поводу того зачем нужны форвард объявления хорошо описано в этой книге (ссылка) (см. раздел 2.3)

--Добавлено чуть позже--------------------------------------------------------------------------

Этого вообще не понял
Цитата(Iron Bug @ 31.10.2010, 12:08) *
всё объясняется проще: когда мелкософтовский компилер собирает модули, он считает, что если нет экземпляра шаблонного класса - то его описание можно просто выкинуть. это и есть баг компилера, его несоответствие стандарту. просто для MSVC нужно, чтобы либо инклюд был явно включен в файл, где шаблон будет использован, либо вот так вот, как ты описал, извратиться и заставить компилер учесть шаблонный класс методом создания фиктивного объекта.

Разберем по частям
Цитата
когда мелкософтовский компилер собирает модули, он считает, что если нет экземпляра шаблонного класса - то его описание можно просто выкинуть.
совершенно правильно считает
Цитата
просто для MSVC нужно, чтобы либо инклюд был явно включен в файл, где шаблон будет использован
а как вы собираетесь использовать класс, если в данном листе трансляции ничего про него не известно? Естественно нужно делать инклуд, и шаблоны тут не при чем

Цитата
либо вот так вот, как ты описал, извратиться и заставить компилер учесть шаблонный класс методом создания фиктивного объекта
какой еще фиктивный объект? Где вы его увидели? Там лишь форвард объявление шаблонного класса, никаких объектов не создается
Алексей1153 Дата 31.10.2010, 12:52
  экономия времени будет. По крайней мере в студии это очень заметно :)

Например, класс A (не шаблон), описанный в хедере, не используется в некоем cpp, но из-за вложенности хедеров попал в начало этого cpp. Компилятор его лишний раз скомпилирует (потому что это только у шаблонов не компилируется неиспользыемое).

В случае же разнесения кода по A.h и A.cpp , компиляция пройдёт шустрее, так как компилироваться класс A будет всего один раз.

Проверить можно так: пусть класс A целиком сидит в A.cpp

Можно написать в любой его функции строчку
{int i;} //компилятор выдаст предупреждение, что не использована переменная


Везде, где инклуд A.h используется, предупреждение появится (ровно столько же раз, сколько заинклужено)
Iron Bug Дата 31.10.2010, 12:08
 
Цитата(daorus @ 31.10.2010, 13:55) *
Исторически появились как необходимость кросс-вставки классов.

воот. так что кроме ссылок на самого себя и циклических ссылок это, конечно, можно, но нафиг нигде не нужно. ибо всё,что нужно компилеру - это увидеть описание класса до его использования в коде, что, в случае простого использования класса, достигается вставкой инклюда в одном месте кода, как правило в заголовочнике, где он используется. а в обычном случае, без циклических ссылок, предварительные объявления без инклюда, тем более для стандартно или библиотечно определённых шаблонов, ни к чему, кроме ещё одного лишнего прохода при компиляции, не приводят. куда ты его вставишь - дело десятое. если класс сам по себе используется, то компилятор обработает его один раз. так что "экономия" времени компиляции будет только в случае библиотеки, которая оперирует только указателями и никогда не обращается к самому классу.

Цитата(Алексей1153 @ 31.10.2010, 13:34) *
о да. Столкнулся несколько раз, пытался решить, спрашивал советы - так и оставил в заголовочнике весь шаблон.

я как-то тоже напоролась на это. это баг мелкософта. об этом написано где-то в MSDN, только мелким-мелким шрифтом на страничке, которую так просто и не найти :) там порядка восьми несовместимостей со стандартом у них имеется. в прочих компилерах этого нет.

Цитата(daorus @ 31.10.2010, 13:55) *
Топик начался с того, что для шаблонных классов создание обычной декларации не катит, а как катит я не знал. И тут мне на форуме подсказали супер-мегафичу, которую я домыслил и оказалось, что для шаблонов форвард-декларацией является как бы создание экземлпяра шаблона! + кстати, подсказанный пример можно существенно сократить, выкинув сигнатуры классов в шаблоне KEY, T. Главное - сохранить кол-во классов в шаблоне.

всё объясняется проще: когда мелкософтовский компилер собирает модули, он считает, что если нет экземпляра шаблонного класса - то его описание можно просто выкинуть. это и есть баг компилера, его несоответствие стандарту. просто для MSVC нужно, чтобы либо инклюд был явно включен в файл, где шаблон будет использован, либо вот так вот, как ты описал, извратиться и заставить компилер учесть шаблонный класс методом создания фиктивного объекта.
daorus Дата 31.10.2010, 11:55
  Iron Bug, во-первых, привет земляку. Я тоже из Екатеринбурга.
Цитата
но в примере никакой форвард-декларации нет

Форвард-декларация - это такой способ сэкономить время на компилции. Форвард декларация - это простое сообщение о существовании сигнатуры. А декларация - это подробное разъяснение, что за этой сигнатурой скрывается. Форвард-деклараци - это любая функция или класс, в синтаксисе которых отсутствуют фигурные скобки - это основной признак форвад-декларации. Исторически появились как необходимость кросс-вставки классов.
class A { B b }; class B { A a }; // error
// вот и появилась форвард-декларация
class B; class A { B b; }; class B { A a; }; // ok
// на самом деле тоже не ок, для ок'я нужны указатели, см. ниже

Ну а сегодня, её юзают тупо для сокращения времени компиляции, если есть возможность обойтись одними указателями на класс или функцию, потому что размер указателя вне зависимости от типа есть константа.
class B; class A { B* b; }; // ok
class B; class A { B b; }; // error
class B{}; class A { B b; }; // ok


Топик начался с того, что для шаблонных классов создание обычной декларации не катит, а как катит я не знал. И тут мне на форуме подсказали супер-мегафичу, которую я домыслил и оказалось, что для шаблонов форвард-декларацией является как бы создание экземлпяра шаблона! + кстати, подсказанный пример можно существенно сократить, выкинув сигнатуры классов в шаблоне KEY, T. Главное - сохранить кол-во классов в шаблоне.

class a; // обычный форвард
template<class, class> b; // шаблонный форвард

class A { a* ptr; }; // юз обычного класса
class B { b<a,a>* ptr; }; // юз шаблонного
Алексей1153 Дата 31.10.2010, 11:34
 
Цитата(Iron Bug @ 31.10.2010, 14:08) *
то есть, в заголовочнике должен быть весь класс и заголовочник должен быть указан до использования где-либо в коде.

о да. Столкнулся несколько раз, пытался решить, спрашивал советы - так и оставил в заголовочнике весь шаблон.
Но душа то не удовлетворена ))) Изворачивался-таки, разделял шаблон на шаблонную составляющую и обычную. Последняя составляющая обычно гораздо объёмнее шаблонной, так что оно того стОило :) Для разделения применялись все нечестные приёмы: преобразование указателя к void* , указатель на коллбэк, так же преобразованный к void*, а где надо - приводимый к нужному указателю
Litkevich Yuriy Дата 31.10.2010, 11:30
 
Цитата(Iron Bug @ 31.10.2010, 14:08) *
когда класс ссылается сам на себя или на потомков
не только. Любой другой класс тоже может быть использован.
Iron Bug Дата 31.10.2010, 11:08
 
Цитата(daorus @ 30.10.2010, 22:18) *
Какой синтаксис форвад-декларации для типа хеш, если я хочу в классе хранить на него указатель

а где в приведённом коде форвард-декларация-то? форвард-декларацией называется случай, когда класс ссылается сам на себя или на потомков. ну и всё сказанное (насчёт указателей) тогда справедливо. но в примере никакой форвард-декларации нет. обычное использование шаблонного класса. стандартного инклюда должно хватить. главное, если компилить под вендой, с MSVC, то нельзя выносить реализацию шаблонного класса из его объявления (это баг MSVC, несовместимость со стандартами). то есть, в заголовочнике должен быть весь класс и заголовочник должен быть указан до использования где-либо в коде.
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 29.3.2024, 0:37