Эта программа правильно сформирована
Цитирование [temp.explicit] / 1 [ выделение мое]:
A Класс, функция, переменная или специализация шаблона члена могут быть явно созданы из его шаблона. функция-член , класс-член или stati c элемент-член шаблона класса может быть явно создан из определения члена, связанного с его шаблоном класса . [..]
И, цитируя [temp.explicit] / 9 [ выделение мое]:
An явное определение экземпляра , которое именует специализацию шаблона класса явно создает экземпляр специализации шаблона класса , а является явным определением экземпляра только тех членов, которые были определены в момент создания .
Таким образом, в примере OP явное определение экземпляра stack<T>
не будет включать явное определение экземпляра конструктора, так как явное определение экземпляра stack<T>
помещено до с предоставлением определения его конструктора через .tpp
include.
Цитирование [temp.point] / 8 [ выделение mine]:
Специализация для шаблона функции, шаблона функции-члена или функции-члена или stati c члена данных элемента шаблон класса может иметь мю В нескольких точках инстанции в единице перевода и в дополнение к точкам инстанцирования, описанным выше, для любой такой специализации, которая имеет точку инстанцирования в единице перевода, также считается конец единицы перевода точка создания экземпляра. Специализация для шаблона класса имеет не более одной точки создания экземпляра в единице перевода. Специализация для любого шаблона может иметь точки реализации в нескольких единицах перевода. Если две разные точки инстанцирования придают специализации шаблона разные значения в соответствии с правилом единого определения, программа некорректна, диагностика не требуется c не требуется.
Таким образом , для случаев, когда stack.cpp
включает в себя две разные точки инстанцирования, и где один до и один после включения stack.tpp
, то программа плохо сформирована.
Однако здесь она становится немного сложно, так как точки реализации зависят от того, как используется шаблон класса и его функция-член (/ конструктор). Как указано в приведенном выше [temp.explicit] / 9 , явное создание экземпляра stack<T>
не приведет к явному определению экземпляра его конструктора, и вместо этого нам нужно будет вернуться к [temp.point] для подробностей, в частности пунктов 1, 2 и 4, о , когда его контекст использования приведет к точке создания до включения stack.tpp
.
Автономный пример в вопросе не охватывается ни одним из этих случаев, и поэтому программа us не плохо сформирована.
G CC vs clang: казалось бы, другое поведение экземпляра ?
Может кто-нибудь сказать мне, как я могу получить символы конструктора для моего шаблона класса, используя clang ++?
Поскольку конструктор никогда не используется, он никогда не должен (нужно ) создается вообще, но кажется, что (из дампа символа OP) G CC делает это в любом случае (что не является недопустимым), а clang - нет. Если кто-то использует / ссылается на конструктор после включения track.tpp
, то и G CC, и clang естественным образом его создают (для конкретной используемой специализации), поскольку они тогда требуются сделать это.