Шаблоны классов и включают охрану в C ++ - PullRequest
7 голосов
/ 08 марта 2010

Разумно ли включать охранников вокруг шаблонных классов?

Разве шаблонные классы не должны быть обработаны каждый раз, когда вы ссылаетесь на них с другой реализацией?

N.B. В Visual C ++ 2008 я не получаю ошибок, объединяющих два ...

Ответы [ 4 ]

12 голосов
/ 08 марта 2010

Вам нужно включить охранников. Рассмотрим этот код:

// this is t.h
template <typename T>
void f( T t ) {
}

// this is t.cpp
#include "t.h"
#include "t.h"

int main() {
    f( 1 );
}

Это дает ошибку:

t.h:2: error: redefinition of 'template<class T> void f(T)'
t.h:2: error: 'template<class T> void f(T)' previously declared here

Кроме того, заголовки, которые обычно содержат шаблоны, также содержат не шаблонный код.

8 голосов
/ 08 марта 2010

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

Определения шаблонов обычно (т. Е. Если вы не используете export или делаете что-то особенное) в заголовочных файлах, которые должны иметь свою защиту включения. Добавление одного для определения шаблона бесполезно, но не вредно.

2 голосов
/ 08 марта 2010

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

Это способ подчиниться Правилу Одного Определения, когда у вас есть содержимое в заголовочных файлах, так что оно доступно и все еще безопасно. Там могут быть другие заголовочные файлы, которые включают в себя ваши. Когда компилятор компилирует файл модуля, он может видеть #include вашего заголовочного файла много раз, но защитники включаются во второй и последующий раз, чтобы убедиться, что компилятор видит содержимое только один раз.

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

2 голосов
/ 08 марта 2010

Краткий ответ: у каждого юнита, который вы планируете включить более одного раза в любые определения, должна быть защита заголовка. Это с или без шаблонов.

...