#c #templates
#c #шаблоны
Вопрос:
Стандарт ISO 98/03 (раздел 14.3.1), похоже, запрещает использовать тип с внутренней связью в качестве параметра шаблона. (Смотрите пример ниже.) Стандарт C 11 этого не делает. G — использование старого стандарта — позволяет это. Я неправильно понимаю стандарт 03, или g просто пропускает это мимо ушей?
namespace
{
struct hidden { };
}
template<typename T>
struct S
{
T t;
};
int main()
{
S<hidden> s;
return 0;
}
Комментарии:
1. Какая версия g ? Может быть расширением
Ответ №1:
Вы правы, что C 03 не позволяет использовать тип с внутренней связью в качестве параметра типа шаблона, в то время как C 11 позволяет.
Однако я, кажется, вспоминаю, что определения внутри анонимного пространства имен все еще имеют внешнюю связь.
Да, в разделе 3.5 [basic.link]
говорится
Имя, имеющее область пространства имен (3.3.5), имеет внутреннюю связь, если это имя
- шаблон объекта, ссылки, функции или функции, который явно объявлен статическим или,
- объект или ссылка, которые явно объявлены
const
иextern
не объявлены явно и не объявлены ранее, чтобы иметь внешнюю связь; или- член данных анонимного объединения.
Имя, имеющее область пространства имен, имеет внешнюю связь, если это имя
- объект или ссылка, если у него нет внутренней связи; или
- функция, если она не имеет внутренней связи; или
- именованный класс (пункт 9) или безымянный класс, определенный в объявлении typedef, в котором класс имеет имя typedef для целей компоновки (7.1.3); или
- именованное перечисление (7.2) или безымянное перечисление, определенное в объявлении typedef, в котором перечисление имеет имя typedef для целей компоновки (7.1.3); или
- перечислитель, принадлежащий перечислению с внешней связью; или
- шаблон, если только это не шаблон функции, имеющий внутреннюю связь (пункт 14); или
- пространство имен (7.3), если оно не объявлено в безымянном пространстве имен.
У вас есть именованный класс в области пространства имен, он имеет внешнюю связь.
И сноска внизу страницы 115 стандарта ISO / IEC 14882: 2003 разъясняет:
Хотя сущности в неназванном пространстве имен могут иметь внешнюю связь, они эффективно квалифицируются именем, уникальным для их единицы перевода, и поэтому их никогда нельзя увидеть из любой другой единицы перевода.
Если у вас есть другая версия, попробуйте посмотреть в разделе 7.3.1.1 [namespace.unnamed]
Ответ №2:
Это недопустимый пример правила. hidden
Класс в вашем примере имеет внешнюю связь. (Он имеет уникальное имя, сгенерированное компилятором, так что ничто за пределами текущей единицы перевода не может фактически связать с ним, но оно все равно внешнее.)
Стандарт дает пример локального типа:
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as template-argument
X<S*> x4; // error: pointer to local type used as template-argument
}