Последствия объявления шаблона и определения

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

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

  2. Что, если таковые имеются, недостатки наличия объявления и определения в том же файле?

  3. Что считают лучшей практикой когда дело доходит до объявления шаблона и определения?

11
задан Trevor Hickey 3 March 2016 в 03:49
поделиться

5 ответов

Как организовать исходный код шаблона

В основном, у вас есть следующие возможности:

  • Сделать определение шаблона видимым для компилятора в точке инстанцирования.
  • Создайте нужные типы в отдельном модуле компиляции, чтобы компоновщик мог их найти.
  • Экспорт по ключевым словам (если доступен)
12
ответ дан 3 December 2019 в 08:29
поделиться

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

Вы можете реализовать шаблоны в отдельном файле, а затем включить этот файл из файла .h. Например:

templ.h

template<class V> V foo(const V& rhs);
#include "templ.inc"

templ.inc

template<class V> V foo*const V& rhs)
{
// do something...
return val;
}

Я лично предпочитаю реализовывать шаблоны прямо в файле h, если они не станут большими, а затем я разделю его на файлы h и inc.

2
ответ дан 3 December 2019 в 08:29
поделиться

При выпуске версии 1.7 для svn diff будет установлен переключатель --show-copy-as-add . Это хороший признак того, что версии до 1.6 не обладают такой способностью.

-121--1667â-

Все ответы, приведенные до сих пор, сводятся к следующему: избегайте вызова delete .

При каждом вызове delete программистом может произойти утечка памяти. Вместо этого автоматически выполните вызов delete . C++ гарантирует, что локальные объекты будут вызываться при выходе из области действия. Используйте эту гарантию для автоматического удаления выделенных ресурсов памяти.

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

Поскольку это такой широко используемый метод, были созданы классы интеллектуальных указателей, которые уменьшают количество кода шаблона. Вместо выделения памяти их конструкторы берут указатель на уже сделанное выделение памяти и сохраняют его. Когда смарт-указатель выходит из области действия, он может удалить распределение.

Конечно, в зависимости от использования, может быть вызвана разная семантика. Вам просто нужен простой случай, когда распределение должно длиться ровно столько, сколько живет класс обертки? Затем используйте boost:: scoped _ ptr или, если вы не можете использовать boost, std:: auto _ ptr . Есть ли неизвестное количество объектов, ссылающихся на распределение, не зная, как долго будет жить каждый из них? Тогда отсчитанный по ссылке boost:: shared _ ptr является хорошим решением.

Но вам не нужно использовать смарт-указатели. Стандартные контейнеры библиотеки тоже делают этот трюк. Они внутренне распределяют память, необходимую для хранения копий объектов, помещенных в них, и при удалении снова освобождают память. Таким образом, пользователю не требуется вызывать new или delete .

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

Но все они имеют общий ответ на ваш вопрос: RAI идиома: приобретение ресурсов - это инициализация. Выделение памяти - это своего рода ресурс. Ресурсы должны быть получены при инициализации объекта и освобождены объектом при его уничтожении.

Сделайте так, чтобы область C++ и правила срока службы выполняли вашу работу за вас. Никогда не вызывайте delete вне объекта RAI, независимо от того, является ли он классом-контейнером, смарт-указателем или какой-либо специальной оболочкой для одиночного выделения. Разрешить объекту обрабатывать назначенный ему ресурс.

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

-121--3515212-
  1. На самом деле нет. Определение шаблона должно быть доступно во время компиляции, поскольку экземпляры шаблонов создаются в зависимости от приведенных аргументов шаблона. Поэтому они должны быть помещены в заголовки, чтобы компилятор мог иметь код для записи нового экземпляра. Вам нужен компилятор с поддержкой ключевого слова export.

  2. Люди могут видеть ваш код, если это недостаток для вас. Это также может быть менее «аккуратно» для некоторых людей, но я не думаю, что это проблема.

0
ответ дан 3 December 2019 в 08:29
поделиться

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

{{1 }}
0
ответ дан 3 December 2019 в 08:29
поделиться

'Обратите внимание, что покупка собственного приложения противоречит политике Google Checkout. При попытке приобрести собственное приложение появится сообщение об ошибке. "

Не похоже. Почему вы хотите купить собственное приложение?

-121--1386578-

Как сказал Дарин Димитров, Последовательности. Contains (последовательность, StringComparison) не существует в качестве метода для типа Последовательностей .

System.Linq.Enumerable , однако, содержит такую подпись. И последовательность также является IEnumerable < char > , поэтому компилятор путается. Вы действительно сможете использовать Linq и компилировать, если замените StringCompar- ison на ICompar- er из Char :

if (myString.Contains(strVar, Comparer<Char>.Default))
{
    // Code here                  
}
-121--3153471-
  1. На самом деле. Существует ключевое слово export , но большинство компиляторов не поддерживают его. Единственный мейнстрим, который я знаю об этом поддерживает, это компилятор Comeau .
  2. Если ваш шаблон является частью открытого API, вы раскрываете свой код миру. (большинство людей не считают это проблемой, но некоторые считают. Это зависит от вашего бизнеса).
  3. Поместите их оба в один и тот же файл заголовка.
0
ответ дан 3 December 2019 в 08:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: