2015-05-29 3 views
8

Являются ли множественные экземпляры одного и того же типа шаблонов одного типа разрешенными в разных единицах компиляции? Как насчет шаблонов функций?Связывание явного создания шаблона класса

пример кода выглядит следующим образом:

test.hpp

template <typename T> 
class A 
{ 
    public: 
     T out(); 
}; 

template <typename T> 
T A<T>::out() 
{ 
    return T(1); 
} 

test1.cpp

#include "test.hpp" 
template class A<int>; 
int testFn() 
{ 
    return A<int>().out(); 
} 

test2.cpp

#include "test.hpp" 
template class A<int>; 
extern int testFn(); 
int main() 
{ 
    return testFn() == A<int>().out(); 
} 

Если я бегу

g++ -std=c++11 test1.cpp test2.cpp -o test 

он компилируется без жалобы на дублированные определения.

Я ссылался на старые черновики стандарта [1] [2], и предполагая, что часть сцепления не изменяется слишком сильно (за исключением анонимных пространств имен). Шаблон класса имеет внешнюю связь на 3.5p4 и 14p4. Если это так, я ожидаю, что g ++ должен жаловаться на дублированные определения A :: out(). Я что-то упустил?

Что делать, если test.hpp определяет шаблон функции без «статического» или «встроенного»?

спасибо.

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf [2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

+2

[temp.spec] p5 * "Для данного шаблона и заданного набора шаблонов-аргументов - определение явного инстанцирования должно появляться не более одного раза в программе [...] Реализация не требуется для диагностики нарушение этого правила ». * – dyp

+0

См. также [CWG NAD 1045] (http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1045), в котором содержится причина, по которой это, вероятно, не диагноз. – dyp

+0

@ dyp. В этом случае моя программа фактически нарушает 14.7.0.5, но стандарт говорит, что g ++ не требуется для диагностики этого и фактически g ++ решил множественное определение. Но чтобы он был стандартным, я должен определить все экземпляры только в одном модуле перевода и объявить («extern») явное создание шаблона в других единицах перевода. Я прав? – nocte107

ответ

1

Хороший способ, чтобы найти ответы на эти вопросы в реализации заключается в использовании «нм». Часто искаженные символы C++ более читабельны, если вы передаете выходные данные от nm до C++ filt.

Например, если вы скомпилировали с помощью «-c» для создания «.o» каждого блока компиляции, вы можете запустить nm. Когда я это делаю, я вижу, что члены шаблона являются слабыми символами кода «W» (на x86 linux). Это означает, что несколько определений в порядке и в определенной системе. Если я создаю функцию, которая не templatized, она будет отображаться как «T» в обоих единицах перевода соответствующих объектных файлов. Это вызовет множественный определенный символ.

Обычно шаблоны C++ создаются по мере необходимости (без полного экземпляра), что позволит вам использовать заголовок типа _impl в дополнение к заголовку объявления.

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

+0

В вашем ответе вы упомянули «в определенной системе». Означает ли это, что он не указан стандартом и может быть не переносимым? Что касается моего последнего вопроса о шаблонах функций, я имею в виду более общие шаблоны функций, а не шаблоны функций членов класса. Спасибо. – nocte107

Смежные вопросы