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

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

14.05.2015, 17:21. Показов 4682. Ответов 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
196 / 197 / 120
Регистрация: 27.05.2011
Сообщений: 545
14.05.2015, 18:39
В каждой единице трансляции просходит инстанцирование шаблона, однако, если параметр одинаковый, то и тип тоже будет одинаковый.
Чтобы ускорить компиляцию, можно использовать предкомпилированные заголовки. Тут уж читайте докуентацию к своему компилятору. Например, gcc, когда встречает директиву #include, ищет вначале файл с расширением *.gch, если он его находит, то использует его. Иначе используется файл, как указано в директиве
1
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
14.05.2015, 19:01
Цитата Сообщение от aLarman Посмотреть сообщение
сколько раз происходит подстановка этого типа?
В общем случае столько, сколько единиц трансляции, использующих шаблон, в твоем проекте.
Но компиляторы нынче умные. Умеют сами это распознавать и не генерят лишнего. По крайней мере на этапе линковки все лишние инстанции выкидываются. Хотя раньше это было причиной нападок на шаблоны С++, мол раздувают код.

Цитата Сообщение от aLarman Посмотреть сообщение
т.е сделать как то чтобы подстановка производилась 1 раз
Если нужны гарантии, то помогут явное инстанцирование и extern template из С++11.

Суть приема в следующем:
Делаешь свой h-ник в таком виде:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
enum MyEnum
{
    enum1 = 0,
    enum2 = 1
};
 
template<MyEnum param>
class MyClass
{
   //...
};
 
extern template class MyClass<enum1>;
Последней строкой мы говорим, что данный шаблон уже проинстанцирован для аргумента enum1 в каком-то другом объектном омдуле, поэтому повтороное инстанцирование производить не нужно.

Теперь допустим у нас есть три файла, в которых наш заголовочный файл подключается.
В одном из этих файлов произведем явное инстанцирование:
C++
1
2
3
#include "твой_заголовочный_файл_с_шаблоном.h"
 
template class MyClass<enum1>; //явное инстанцирование
Это строка принудительно заставит сгенерировать инстанцию для данного объектного модуля. Т.к. Для аргумента enum1 была указана внешняя инстанция в h-файле, компилятор поставит ссылку, по которой линкер потом найдет определение инстанции в этой файле.
Далее можно пользоваться шаблоном как обычно.

___
Но. Я не рекомендую злоупотреблять данной техникой. Даже может быть когда она может дать прирост в скорости компиляции. Т.к. необходимость ручного контроля инстанций приведет к снижению общей сопровождаемости кода. И компиляторы сейчас довольно шустрые, гораздо быстрее чем были раньше.
5
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 10:01  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Если нужны гарантии, то помогут явное инстанцирование и extern template из С++11.
вот печаль, не низя пока что 11ый стд

Добавлено через 4 минуты
я попробовал такую вещь, но наверное сам не до конца понял как оно работает
.h - с шаблонным классом
несколько .cpp где юзается указатель на шаблонный класс(в таком случае происходит подстановка типа?)

есть еще .h где есть метод(только объявлен, метод так же шаблонный), который возвращает каждый раз новый указатель на шаблонный класс
типо того
C++
1
2
template<typename T>
MyClass<T> * getNewInstance();
.cpp - в нем реализация этого метода,с конкретным подставленным типом т.е
C++
1
2
3
4
5
template<>
MyClass<enum1> * getNewInstance()
{
return new MyClass<enum1>();
}
время компиляции сократилось на треть, что тут произошло?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 10:47
Цитата Сообщение от aLarman Посмотреть сообщение
время компиляции сократилось на треть, что тут произошло?
Ты добавил полную специализацию функции. Полная специализация - это уже никакой не шаблон. Поэтому и сократилось.
Как вариант, если твой код позволяет это сделать, то почему бы и нет.
Просто такое не всегда возможно.
В принципе, централизованый подход для сокращения времени компиляции - использование предкомпилированных заголовков. см. первый ответ в теме.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 11:13  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Как вариант, если твой код позволяет это сделать, то почему бы и нет.
да позволяет
так что произошло с подстановкой типа в классе MyClass ? один раз подставилось или в каждой единице трансляции
(наверное забыл сказать что теперь в каждый .cpp подключаем .h где есть метод getNewInstatnce и дергаем его)
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 11:23
Цитата Сообщение от aLarman Посмотреть сообщение
один раз подставилось
Инстанцирования не будет в остальных файлах, т.к. у тебя нет доступного полного определения шаблона.
Т.е. твой код жестко приколочен к одной специализации. Если T будет отличным от enum1 (кстати почему typename, был же enum?), то будет ошибка линковки.
Вероятно корректнее будет сделать так (чтобы не ломалось для сотальных T):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// в h
 
// главный шаблон
template<typename T>
MyClass<T> * getNewInstance()
{
    return new MyClass<T>();
}
 
// Специализация для enum1
template <>
MyClass<enum1> * getNewInstance();
 
// в cpp:
template<>
MyClass<enum1> * getNewInstance()
{
    return new MyClass<enum1>();
}
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 11:27  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Т.е. твой код жестко приколочен к одной специализации. Если T будет отличным от enum1 (кстати почему typename, был же enum?), то будет ошибка линковки.
Вероятно корректнее будет сделать так (чтобы не ломалось для сотальных T):
ну я может не так привел код, в принципе то он собирается

все таки почему подставляется один раз то? я честно не понял
мы же .cpp файлах юзаем указатель на класс конкретно инстанциированный определенным типом, подстановка для класса будет в этих .срр или нет, а если нет то почему?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 11:36
Цитата Сообщение от aLarman Посмотреть сообщение
все таки почему подставляется один раз то? я честно не понял
Потому что для инстанцирования нужно полное определение шаблона. Ты из заголовочника убрал тело шаблона, и добавил специализацию в одну из единиц трансляции. Компилятор будет считать, что определение шаблона уже где-то инстанцировано. Но инстанций у тебя нет, зато есть специализация. Специализация будет найдена линкером. Если T будет отличным от заявленного в специализации, то линкер ее не найдет. И будет ошибка.
У тебя либо нет других аргументов кроме enum1, либо где-то все-таки есть инстанции для остальных аргументов, либо ты привел неполный код.
Тут столько вариантов, что приводя некорректные или неполные примеры можно кардинально разный ответ получить.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 12:15  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
enum MyEnum
{
    enum1 = 0,
    enum2 = 1
};
MyClass.h 
template<MyEnum param>
class MyClass
{
   //...
};
test1.cpp

C++
1
2
#include "Instance.h"
MyClass<enum1> * ptr;//не глобальный спрятан в теле класса
test2.cpp

C++
1
2
#include "Instance.h"
MyClass<enum1> * ptr;//не глобальный спрятан в теле класса
testN.cpp

C++
1
2
#include "Instance.h"
MyClass<enum1> * ptr;//не глобальный спрятан в теле класса
Instance.h
C++
1
2
3
#include "MyClass.h"
template<typename T>
MyClass<T> * getNewInstance();
Instance.cpp

C++
1
2
3
4
5
6
#include "Instance.h"
template<>
MyClass<enum1> * getNewInstance()
{
    return new MyClass<enum1>();
}
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 12:42
aLarman, ну вот. Видишь же, кроме enum1 нет других параметров.
Добавь использование для enum2, и увидишь ошибку.
Поэтому перепиши заголовочник как в посте 7.
У тебя вопросы еще остались, ели все понятно?
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 12:47  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
У тебя вопросы еще остались, ели все понятно?
да остались
Цитата Сообщение от DrOffset Посмотреть сообщение
Добавь использование для enum2, и увидишь ошибку.
это не требуется в этом случаем, использование другого параметра может потребоваться только в другом наборе .cpp файлов, сейчас рассматриваем вариант без этого набора
и собсно вопросы, 1)почему если сделать так как написано в 10ом посте, то время компиляции сокращается(точнее за счет чего)
2) подстановка типа для класса MyClass будет так же производиться в каждом .cpp фале или только один раз в Instance.cpp
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 12:50
Цитата Сообщение от aLarman Посмотреть сообщение
1)почему если сделать так как написано в 10ом посте, то время компиляции сокращается(точнее за счет чего)
Засчет того, что инстанцирование не выполняется, если нет тела шаблона. См ответы выше.

Цитата Сообщение от aLarman Посмотреть сообщение
2) подстановка типа для класса MyClass будет так же производиться в каждом .cpp фале или только один раз в Instance.cpp
Подстановка будет выполнятся, а вот инстанцирование - нет. При подстановке просто будет получено имя функции, которое соответствует твоей специализации. На этом все закончится. Т.е. этот код формально мало чем отличается от вызова обычной, нешаблонной функции.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 12:53  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
В общем случае столько, сколько единиц трансляции, использующих шаблон, в твоем проекте.
так все таки инстанциирование MyClass типом enum1 будет производится в каждом .cpp файле или нет?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 12:55
Цитата Сообщение от aLarman Посмотреть сообщение
так все таки инстанциирование MyClass типом enum1 будет производится в каждом .cpp файле или нет?
Ну ты же разный код показывал, в начале поста и сейчас. В начале у тебя было тело в заголовочнике целиком. Поэтому я говорил, что инстанцирование будет в каждом файле.
Сейчас ты убрал тело, поэтому инстанцирования не будет вообще.
Вроде бы все понятно, нет?
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 13:03  [ТС]
DrOffset, я сам просто больше запутался, вот и Вас запутываю похоже
есть 2 варинта - 1ый как в заголовке, т.е каждый .cpp тянет .h, в каждом .cpp есть указатель на
C++
1
MyClass<enum1> * p = new MyClass<enum1>();
тут получается что из каждого .срр будет происходить инстанциирование,
так вот, есть 2ой вариант(код в 10ом посте) и
написать в каждом .cpp
C++
1
MyClass<enum1> * p = getNewInstance<enum1>();
тогда сокращается время компиляции за счет чего? за счет того что инстанциирование теперь производится один раз? или по прежнему в каждом .срр?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 13:11
Цитата Сообщение от aLarman Посмотреть сообщение
вот и Вас запутываю похоже
Ничего подобного. Тут все как на ладони
Цитата Сообщение от aLarman Посмотреть сообщение
тогда сокращается время компиляции за счет чего? за счет того что инстанциирование теперь производится один раз? или по прежнему в каждом .срр?
Ты почему-то меня невнимательно читаешь.
Я же уже отвечал на этот вопрос несколько раз
Инстанцирования не будет вообще! Потому что ты убрал тело шаблона.
Ты добавил специализацию для enum1, эта специализация - теперь не шаблон, а обычная функция. В других файлах будет подстановка аргумента и генерация имени функции с учетом этого. Т.к. тела шаблона нет, то компилятор никакого кода больше не генерирует, а вставляет ссылку для линкера, мол, вот такая-то функция, где-то есть. Потом, когда линкер производит связывание, он находит определение этого имени в виде твоей специализации.
Все.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 13:45  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Все.
круто, теперь это я понял
еще маленький момЭнт, а указатель же присутствует, для него не будет инстанциирования?
по большому счету что выходит, 1ый варинат new в каждом .срр, 2ой варинат - в одном
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
15.05.2015, 13:49
Лучший ответ Сообщение было отмечено aLarman как решение

Решение

Цитата Сообщение от aLarman Посмотреть сообщение
для него не будет инстанциирования?
Для указателя не будет.
Но по другой причине, потому что для определения указателя необязательно полное определение класса иметь. Компилятор инстанцирует лениво, поэтому инстанцирование для класса будет там, где был вызван new.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 13:53  [ТС]
кажется это то что я хотел услышать!!!спасибо!!!

Добавлено через 1 минуту
во вдогоночку раз такая пьянка
C++
1
class Derived : public MyClass<enum1>//явно тип указали
т.к же будет инстанциирование?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.05.2015, 13:53
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
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. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru