#c #templates #gcc #namespaces #clang
#c #шаблоны #gcc #пространства имен #clang
Вопрос:
Я пытаюсь повторно использовать существующие шаблонные функции из пространства имен в моем собственном пространстве имен и явно создавать их экземпляры из соображений покрытия кода.
Следующий код компилируется с помощью gcc 9.3, но не компилируется с clang 10.0.0
namespace bar {
template<typename T>
T func(T arg){ return arg;};
}
namespace foo {
using bar::func;
}
template int foo::func<int>(int);
int main()
{ }
Посмотреть пример здесь
Если я создаю экземпляр функции шаблона как
template int bar::func<int>(int);
clang также компилируется. Но это не то, что я хочу.
Возможно ли явное создание экземпляра функции шаблона в пространствах имен с помощью clang?
Почему gcc и clang дают разные результаты?
Ответ №1:
Боюсь, вы не можете этого сделать. Clang верен.
[temp.explicit]
2 Синтаксис для явного создания экземпляра:
явное создание экземпляра: объявление шаблона extern opt4 Если явное создание экземпляра предназначено для класса или класса-члена, детализированный спецификатор типа в объявлении должен включать идентификатор простого шаблона; в противном случае объявление должно быть простым объявлением, список инициализации которого содержит один инициализирующий декларатор, у которого нет инициализатора.
В этом абзаце говорится, что бит после template
ключевого слова должен быть как синтаксически, так и семантически допустимым объявлением для чего-либо (и не должен содержать инициализатор, который здесь неуместен). Объявление состоит из нескольких частей, но интерес здесь представляет часть объявления declarator.
Об этом у нас есть следующий абзац
[dcl.значение] (выделение мое)
1 Декларатор содержит ровно один идентификатор декларатора; он называет объявленный идентификатор. Неквалифицированный идентификатор, встречающийся в идентификаторе декларатора, должен быть простым идентификатором, за исключением объявления некоторых специальных функций ([class.ctor], [class.conv], [class.dtor], [over.oper] ) и для объявления специализаций шаблонов или частичных специализаций ([temp.spec]). Когда указан идентификатор декларатора, объявление должно ссылаться на ранее объявленный член класса или пространства имен, на который ссылается квалификатор (или, в случае пространства имен, элемента встроенного набора пространств имен этого пространства имен ([namespace.def] )) или на специализациюиз-за этого; член не должен быть просто введен с помощью объявления using в области класса или пространства имен, назначенного спецификатором вложенного имени идентификатора декларатора.
Поскольку ваш идентификатор декларатора в явном создании экземпляра шаблона есть foo::func
, он не соответствует правилу, изложенному в предложении, которое я выделил жирным шрифтом. Это делает вашу попытку явного создания экземпляра некорректной.
GCC также должен был отклонить вашу попытку.