Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/21: Рейтинг темы: голосов - 21, средняя оценка - 4.62
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124

Подстановка типа\шаблоны с++

14.05.2015, 17:21. Показов 4684. Ответов 38
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день, не могу разобраться
представим есть классец находится в .h

C++
1
2
3
4
5
6
7
8
9
10
enum MyEnum
{
enum1 = 0,
enum2 = 1
}
template<MyEnum param>
classMyClass
{
//и т.д начинка класс
};
класс большой

далее, есть предположим 2-3 .cpp файла, который тянут этот хедер с этим классом
в каждом .срр создается объект этого класса, причем в качестве шаблонного параметр всегда одно значение, пусть enum1
сколько раз происходит подстановка этого типа?
если несколько раз, то можно ли ускорить сборку? т.е сделать как то чтобы подстановка производилась 1 раз
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
14.05.2015, 17:21
Ответы с готовыми решениями:

Подстановка вычисляемого типа в шаблонах
Товарищи. Помогите разобраться с шаблонами. С шаблонами начал разбираться вчера, и потому излагаю задачу полностью, дабы не быть...

Шаблоны изменение типа
Передо мной стоит такая задача: class par1; class par2; class par3; class MyClass //Основной класс {

Шаблоны типа template<class T*>
Здравствуйте, объясните пожалуйста, что означает сия запись: template&lt;class T*&gt;. И означает ли она, что я далее смогу использовать только...

38
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 13:56
Студворк — интернет-сервис помощи студентам
Т.е. ты перенес инстанцирование класса в одну единицу трансляции, путем указания специализации для функции, которая создает его экземпляры по шаблону.
Функция инстанцироваться перестала вообще, а класс - теперь инстанцируется только в одном файле.
Если класс очень большой, то это дает выигрыш в скорости построения.
Но тем не менее, осталась проблема инстанцирования другими аргументами, отличными от enum1. В этом случае в отсутствие специализации, либо тела шаблона, будет ошибка линкера.
Если ты добавишь тело и прототип специализации как я показал в посте 7 в заголовочный файл, то не получишь замедления компиляции, но и корректность кода восстановишь.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 13:56  [ТС]
вот и еще что вспомнил
если вместо сырого указателя
например
C++
1
auto_ptr<MyClass<enum1> >
так же неизбежно инстанциирование в каждом .срр
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 13:58
Цитата Сообщение от aLarman Посмотреть сообщение
class Derived : public MyClass<enum1>//явно тип указали
Инстанцирование будет при попытке создать объект Derived. Если создания объекта нет здесь, то и инстанцирования не будет. Не смотря на явную запись аргумента.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 13:59  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Если класс очень большой, то это дает выигрыш в скорости построения.
Но тем не менее, осталась проблема инстанцирования другими аргументами, отличными от enum1. В этом случае в отсутствие специализации, либо тела шаблона, будет ошибка линкера.
я это понимаю, просто при компиляции набора .срр будет использоваться только один тип(MyClass<enum1>)
для другого набора .cpp будет сделана своя специализация
собсно цель - ускорить сборку, ибо тачка 32ядра, и хочется чтобы собиралось все поскорее(собсно .срр это файлы с gtest -ами)

Добавлено через 1 минуту
Цитата Сообщение от DrOffset Посмотреть сообщение
Инстанцирование будет при попытке создать объект Derived
кул
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 14:00
Цитата Сообщение от aLarman Посмотреть сообщение
так же неизбежно инстанциирование в каждом .срр
По правилам должно быть. Из-за деструктора, который требуется для delete. Но по факту это почти всегда можно оптимизировать, вынеся деструктор класса, в котором такой авто_птр сидит, в отдельный файл.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 14:01  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Но по факту это почти всегда можно оптимизировать, вынеся деструктор класса, в котором такой авто_птр сидит в отдельный файл.
честно не совсем понял как это
auto_prt в .cpp же, как быть то?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 14:02
Цитата Сообщение от aLarman Посмотреть сообщение
auto_prt в .cpp же, как быть то?
Код покажи лучше А то может быть мы о разных вещах говорим.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 14:05  [ТС]
ну из поста 10
было
C++
1
MyClass<enum1> * p = getNewInstance<enum1>();
сделать типо того

C++
1
2
std::auto_ptr<MyClass<enum1> > ptr;
ptr.reset(getNewInstatnce<enum1>());
Добавлено через 1 минуту
Цитата Сообщение от DrOffset Посмотреть сообщение
Из-за деструктора, который требуется для delete.
вот незадача, получается если я сделаю так
в .срр
C++
1
2
3
MyClass<enum1> * p = getNewInstance<enum1>();
//поработали с указателем
delete p;
все таки произодйет инстанциирование?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 14:54
Цитата Сообщение от aLarman Посмотреть сообщение
все таки произодйет инстанциирование?
Да, как и в случае с использованием функций и переменных из этого класса. Но это не обязательно будет так. Компилятор может не генерировать инстанцию, если у него достаточно информации для этого.

Цитата Сообщение от aLarman Посмотреть сообщение
сделать типо того
В этом смысле нет разницы с примером без умных указателей.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 15:06  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
В этом смысле нет разницы с примером без умных указателей.
т.е когда в качестве параметр для auto_ptr используется шаблонный класс то при инстанциировании auto_ptr типом MyClass<enum1>, cам класс не инстанциируется?

Добавлено через 6 минут
вобщем, нужна теперь конкретика
если я сделаю сырой указатель
то MyClass<enum1> * p- тут нет инстанциирования
если указатель инициализируется вызовом new то будет инстанциирование, т.к. тут уже пригодился конструкор класса
если иницилизировать указатель методом который дергает new и который определел в другой единице трансляции, то тут будет инстанциирование только один раз(в том месте где определн метод)
если я использую delete p то так же будет инстанциирование, т.к пригодился деструктор
если же сделать еще например метод который будет дергать delete то инстанциирование будет произведено там где определн этот метод(например в том же .срр что и getNewInstance)

если использовать auto_ptr, то опять же что получается
деструктор вызывается тут же(когда объект auto_ptr будет удаляться), его реализация нужна, тогда всегда будет происходить инстанциирование если использовать умный указатель
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 15:10
Цитата Сообщение от aLarman Посмотреть сообщение
т.е когда в качестве параметр для auto_ptr используется шаблонный класс то при инстанциировании auto_ptr типом MyClass<enum1>, cам класс не инстанциируется?
Внутри auto_ptr тот же самый указатель.
До тех пор, пока ты не дергаешь у него методы или не зовешь delete, то инстанцирования точно не будет.
Если например код такой:
C++
1
2
3
4
5
6
7
8
class Some
{
public:
   ~Some(); // определение в отдельном файле
 
private:
    std::auto_ptr< MyClass<enum1> > ptr;
};
То при подключении этого кода в другой файл и создание там объекта не приведет к инстанцированию MyClass<enum1>.
Вот это я имел в виду.
В случае, если ты используешь методы шаблона в данной единице трансляции, то инстанцирование будет.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 15:13  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
В случае, если ты используешь методы шаблона в данной единице трансляции, то инстанцирование будет.
а если так вот создал я указатель
C++
1
MyClass<enum1> * p = getNewInstance<enum1>();
а потом где то
C++
1
p->someMethod()
то И В текущей единице трансляции будет произведено инстанциирование?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 15:26
aLarman, вообще тут надо внести ясность.
Говоря про необходимость или отсутствие необходимости инстанцирования нужно меть в виду, что компилятор в этом плане не должен следовать какому-то конкретному алгоритму (в стандарте есть кое-какие указания, но это скорее сглаживание углов, чем алгоритм "от и до"). Но он всегда исходит из того, чтобы генерировать как можно меньше. Поэтому везде выше, где я говорил, что инстанцирование будет, означает, что оно потенциально возможно, но это не значит, что оно будет в 100% случаев. Важно тут всего несколько вещей:
1) ODR не должно нарушаться, но если оно нарушится, то компилятор ничего про это не обязан говорить.
2) Компилятор не будет генерировать лишнего, если это возможно.

Цитата Сообщение от aLarman Посмотреть сообщение
то И В текущей единице трансляции будет произведено инстанциирование?
Если я правильно понял, то нет.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 15:36  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Если я правильно понял, то нет.
просто уже не логично выходит, если нам нужен конструктор или деструктор(т.е дергаем new или delete) то вроде инстанциирование есть, а если конструктор и декструктор обернуть в методы, и реализовать их в другой единице трансляции то инстанциирование будет там, то почему тогда если дергаем другие методы(не конструктор и не деструктор) через указатель, то вроде и нет инстанциирования, честно, не сходится как то...
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 15:55
aLarman, Вот кое-какая информация насчет реализации инстанцирования в конкретных компиляторах.

Добавлено через 13 минут
Цитата Сообщение от aLarman Посмотреть сообщение
просто уже не логично выходит, если нам нужен конструктор или деструктор(т.е дергаем new или delete) то вроде инстанциирование есть, а если конструктор и декструктор обернуть в методы, и реализовать их в другой единице трансляции то инстанциирование будет там, то почему тогда если дергаем другие методы(не конструктор и не деструктор) через указатель, то вроде и нет инстанциирования, честно, не сходится как то...
Не сходится, потому что ты пытаешься все уложить в одну стратегию поведения.
Вот есть файл a.cpp и файл b.cpp, которые независимо подключают h с шаблоном.
Каждый файл совокупно с своими включаемыми файлами представляет собой единицу трансляции. Файлы компилируются независимо, естественно.
Теперь ты начинаешь работать с классом, в каждом из файлов. Ты вызываешь методы и т.п.
В общем виде, т.е. в той модели компиляции, которая считается основной в С++ (однопроходная компиляция), никак нельзя быть увереным, что соседний файл тоже использует этот класс. Следовательно нельзя положиться на то, что методы, которые мы тут используем, уже содержаться в объектном коде. Поэтому он генерирует и для этого файла и для того, а на этапе линковки убирает лишнее. Но тут возможно варианты. Современные компиляторы в принципе не обязаны поддерживать однопроходную модель компиляции и могут сперва собрать базу данных об использовании шаблонов, что позволит генерировать инстанцию сразу только в одном месте. Или можно использовать, например, предкомпилированные заголовки. Или собирать информацию об инстанциях в процессе компиляции. Или еще как. Это не регламентируется строго.
Теперь касаельно твоего недоумения.
В чем нелогичность? Ты передаешь указатель в функцию, которая неизвестно что делает: неизвестно что - для данной единицы трансляции, т.к. реализация находится в другой. Это не тоже самое, что позвать конкретный известный метод у шаблона. С учетом того, что компилятор не может знать без дополнительных ухищрений о том, что этот метод уже сгенерирован в другой единице трансляции.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 16:35  [ТС]
собсно вывод какой?
C++
1
2
MyClass<enum1> * p  = getNewInstance<enum1>();//не вызывает инстанциирование
p->SomeMethod();//вызывает инстанциирование?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 16:44
Цитата Сообщение от aLarman Посмотреть сообщение
p->SomeMethod();//вызывает инстанциирование?
Да. Вызывает. Опять же в общем случае. Но может не вызывать для конкретной ситуации.
Например, если попытаться смоделировать тест, с функций класса, которая не касается состояния класса, а просто, например, выводит hello world на экран, то компилятор может не генерировать ничего, видя из контекста, что это ни к чему, и сразу вывести текст на экран, без промежуточных вызовов.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 16:58  [ТС]
DrOffset, вот плохо что некоторые вещи все таки не однозначны, нельзя на что то положиться
а Вам спасибо за разъяснения
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 17:13
Цитата Сообщение от aLarman Посмотреть сообщение
DrOffset, вот плохо что некоторые вещи все таки не однозначны, нельзя на что то положиться
Нужно изучать как это сделано в конкретном компиляторе и делать выводы уже на основе этого.
В принципе очень просто сделать тест, на котором проявится все, что я выше говорил. Как в плюс, так и в минус.
Если тебе что-то не понятно, то рекомендую просто делать минитест и смотреть. Мне, например, удалось добиться как полной генерации всех инстанций во всех файлах, так и отсутствия генерации инстанций вообще. Даже в тех файлах, где объект класса создается. Просто меняя уровень оптимизации с -O1 на -O2. И это при том, что в примере функции вызываются у объекта.
Приготовил пример специально, если вдруг все равно было бы непонятно о чем я говорю
Можешь посмотреть во вложении.
Вложения
Тип файла: 7z test-tmpl.7z (1.5 Кб, 3 просмотров)
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.05.2015, 17:13
Помогаю со студенческими работами здесь

Шаблоны. Ошибка приведения типа
Пишу курсовой проект. Шаблонную сортировку по всем полям для каждого класса. template&lt;class Type&gt; void...

Шаблоны, наследование и размер типа
Суть вопроса в том, что имея два шаблона класса, унаследованных от общего предка, и инстанциируя &quot;один другим&quot; имеем + n байт к...

Подстановка в выражение типа string
Имелось выражение, его с помощью convert переделали в string. Теперь я хочу отлавливать символ - степень(т.е. '^') и ту цифру, что стоит...

Подстановка типа в универсальный метод
Всем здравствовать. Вопрос: Можно ли в универсальном методе не указывать тип T явно, а подставлять вместо него некоторую переменную...

Подстановка, зависимые ячейки, подстановка по условию
Доброго времени суток. Предисловие! Можно не читать. Около недели назад начал разрабатывать решение для того чтобы упорядочить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru