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

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

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

Author24 — интернет-сервис помощи студентам
Добрый день, не могу разобраться
представим есть классец находится в .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;. И означает ли...

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

38
196 / 197 / 120
Регистрация: 27.05.2011
Сообщений: 545
14.05.2015, 18:39 2
В каждой единице трансляции просходит инстанцирование шаблона, однако, если параметр одинаковый, то и тип тоже будет одинаковый.
Чтобы ускорить компиляцию, можно использовать предкомпилированные заголовки. Тут уж читайте докуентацию к своему компилятору. Например, gcc, когда встречает директиву #include, ищет вначале файл с расширением *.gch, если он его находит, то использует его. Иначе используется файл, как указано в директиве
1
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
14.05.2015, 19:01 3
Цитата Сообщение от 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  [ТС] 4
Цитата Сообщение от 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
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
15.05.2015, 10:47 5
Цитата Сообщение от aLarman Посмотреть сообщение
время компиляции сократилось на треть, что тут произошло?
Ты добавил полную специализацию функции. Полная специализация - это уже никакой не шаблон. Поэтому и сократилось.
Как вариант, если твой код позволяет это сделать, то почему бы и нет.
Просто такое не всегда возможно.
В принципе, централизованый подход для сокращения времени компиляции - использование предкомпилированных заголовков. см. первый ответ в теме.
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 11:13  [ТС] 6
Цитата Сообщение от DrOffset Посмотреть сообщение
Как вариант, если твой код позволяет это сделать, то почему бы и нет.
да позволяет
так что произошло с подстановкой типа в классе MyClass ? один раз подставилось или в каждой единице трансляции
(наверное забыл сказать что теперь в каждый .cpp подключаем .h где есть метод getNewInstatnce и дергаем его)
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
15.05.2015, 11:23 7
Цитата Сообщение от 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  [ТС] 8
Цитата Сообщение от DrOffset Посмотреть сообщение
Т.е. твой код жестко приколочен к одной специализации. Если T будет отличным от enum1 (кстати почему typename, был же enum?), то будет ошибка линковки.
Вероятно корректнее будет сделать так (чтобы не ломалось для сотальных T):
ну я может не так привел код, в принципе то он собирается

все таки почему подставляется один раз то? я честно не понял
мы же .cpp файлах юзаем указатель на класс конкретно инстанциированный определенным типом, подстановка для класса будет в этих .срр или нет, а если нет то почему?
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
15.05.2015, 11:36 9
Цитата Сообщение от aLarman Посмотреть сообщение
все таки почему подставляется один раз то? я честно не понял
Потому что для инстанцирования нужно полное определение шаблона. Ты из заголовочника убрал тело шаблона, и добавил специализацию в одну из единиц трансляции. Компилятор будет считать, что определение шаблона уже где-то инстанцировано. Но инстанций у тебя нет, зато есть специализация. Специализация будет найдена линкером. Если T будет отличным от заявленного в специализации, то линкер ее не найдет. И будет ошибка.
У тебя либо нет других аргументов кроме enum1, либо где-то все-таки есть инстанции для остальных аргументов, либо ты привел неполный код.
Тут столько вариантов, что приводя некорректные или неполные примеры можно кардинально разный ответ получить.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 12:15  [ТС] 10
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
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
15.05.2015, 12:42 11
aLarman, ну вот. Видишь же, кроме enum1 нет других параметров.
Добавь использование для enum2, и увидишь ошибку.
Поэтому перепиши заголовочник как в посте 7.
У тебя вопросы еще остались, ели все понятно?
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 12:47  [ТС] 12
Цитата Сообщение от DrOffset Посмотреть сообщение
У тебя вопросы еще остались, ели все понятно?
да остались
Цитата Сообщение от DrOffset Посмотреть сообщение
Добавь использование для enum2, и увидишь ошибку.
это не требуется в этом случаем, использование другого параметра может потребоваться только в другом наборе .cpp файлов, сейчас рассматриваем вариант без этого набора
и собсно вопросы, 1)почему если сделать так как написано в 10ом посте, то время компиляции сокращается(точнее за счет чего)
2) подстановка типа для класса MyClass будет так же производиться в каждом .cpp фале или только один раз в Instance.cpp
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
15.05.2015, 12:50 13
Цитата Сообщение от aLarman Посмотреть сообщение
1)почему если сделать так как написано в 10ом посте, то время компиляции сокращается(точнее за счет чего)
Засчет того, что инстанцирование не выполняется, если нет тела шаблона. См ответы выше.

Цитата Сообщение от aLarman Посмотреть сообщение
2) подстановка типа для класса MyClass будет так же производиться в каждом .cpp фале или только один раз в Instance.cpp
Подстановка будет выполнятся, а вот инстанцирование - нет. При подстановке просто будет получено имя функции, которое соответствует твоей специализации. На этом все закончится. Т.е. этот код формально мало чем отличается от вызова обычной, нешаблонной функции.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 12:53  [ТС] 14
Цитата Сообщение от DrOffset Посмотреть сообщение
В общем случае столько, сколько единиц трансляции, использующих шаблон, в твоем проекте.
так все таки инстанциирование MyClass типом enum1 будет производится в каждом .cpp файле или нет?
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
15.05.2015, 12:55 15
Цитата Сообщение от aLarman Посмотреть сообщение
так все таки инстанциирование MyClass типом enum1 будет производится в каждом .cpp файле или нет?
Ну ты же разный код показывал, в начале поста и сейчас. В начале у тебя было тело в заголовочнике целиком. Поэтому я говорил, что инстанцирование будет в каждом файле.
Сейчас ты убрал тело, поэтому инстанцирования не будет вообще.
Вроде бы все понятно, нет?
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 13:03  [ТС] 16
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
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
15.05.2015, 13:11 17
Цитата Сообщение от aLarman Посмотреть сообщение
вот и Вас запутываю похоже
Ничего подобного. Тут все как на ладони
Цитата Сообщение от aLarman Посмотреть сообщение
тогда сокращается время компиляции за счет чего? за счет того что инстанциирование теперь производится один раз? или по прежнему в каждом .срр?
Ты почему-то меня невнимательно читаешь.
Я же уже отвечал на этот вопрос несколько раз
Инстанцирования не будет вообще! Потому что ты убрал тело шаблона.
Ты добавил специализацию для enum1, эта специализация - теперь не шаблон, а обычная функция. В других файлах будет подстановка аргумента и генерация имени функции с учетом этого. Т.к. тела шаблона нет, то компилятор никакого кода больше не генерирует, а вставляет ссылку для линкера, мол, вот такая-то функция, где-то есть. Потом, когда линкер производит связывание, он находит определение этого имени в виде твоей специализации.
Все.
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
15.05.2015, 13:45  [ТС] 18
Цитата Сообщение от DrOffset Посмотреть сообщение
Все.
круто, теперь это я понял
еще маленький момЭнт, а указатель же присутствует, для него не будет инстанциирования?
по большому счету что выходит, 1ый варинат new в каждом .срр, 2ой варинат - в одном
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
15.05.2015, 13:49 19
Лучший ответ Сообщение было отмечено aLarman как решение

Решение

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

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Элементы алгоритмизации
hw_wired 28.01.2025
Основы алгоритмизации В современном мире алгоритмы играют фундаментальную роль в развитии информационных технологий и программирования. Понимание основ алгоритмизации является ключевым элементом в. . .
Человек и информация
hw_wired 28.01.2025
Введение: роль информации в познании мира В современном мире информация играет фундаментальную роль в процессе познания окружающей действительности. Она представляет собой совокупность сведений об. . .
Компьютер и информация
hw_wired 28.01.2025
Эволюция вычислительных машин История развития вычислительной техники начинается задолго до появления первых электронных устройств. Человечество всегда стремилось упростить процесс вычислений и. . .
Информационные технологии
hw_wired 28.01.2025
Введение в современные технологии работы с информацией В современном мире информационные технологии стали неотъемлемой частью практически всех сфер человеческой деятельности. Они существенно. . .
Информация вокруг нас
hw_wired 28.01.2025
Основные понятия информации В современном мире понятие информации является фундаментальным и охватывает практически все сферы человеческой деятельности. Информация представляет собой совокупность. . .
Компьютер для начинающих
hw_wired 28.01.2025
Введение в мир компьютерных технологий В современном мире информация стала одним из важнейших ресурсов человечества, определяющим развитие общества и технологий. Наша жизнь неразрывно связана с. . .
[golang] 189. Rotate Array
alhaos 28.01.2025
Повороты рукоятки, целочисленный слайс нужно сдвинуть на целое положительное число. Мне очень нравится решение на GO / / https:/ / leetcode. com/ studyplan/ top-interview-150/ package topInterview . . .
КуМир: решение задач на матрицы
bytestream 28.01.2025
КуМир представляет собой среду для обучения программированию, которая включает в себя мощные инструменты для работы с матрицами. Матрица в программировании - это двумерный массив, состоящий из. . .
КуМир: решение задач на строки
bytestream 28.01.2025
В системе программирования КуМир работа со строковыми данными является одним из важнейших аспектов создания программ. Строки представляют собой последовательности символов, заключенные в кавычки,. . .
КуМир: решение геометрических задач
bytestream 28.01.2025
Программирование геометрических задач в среде КуМир становится всё более актуальным в обучении школьников и студентов. КуМир — это разработанная в России обучающая программная среда, предназначенная. . .
КуМир, исполнитель Водолей: Задачи и решения
bytestream 28.01.2025
КуМир — это образовательная среда для обучения программированию. Она предлагает пользователям разнообразные инструменты для разработки и отладки программ, что особенно ценно для студентов и. . .
КуМир, исполнитель Чертежник: Решение задач
bytestream 28.01.2025
КуМир (Комплект Учебных МИРов) представляет собой образовательную среду для обучения основам программирования и алгоритмизации. Исполнитель Чертежник работает на координатной плоскости, где может. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru