Внутренний тип в качестве аргумента шаблона - PullRequest
6 голосов
/ 03 ноября 2011

Стандарт 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;
}

Ответы [ 2 ]

7 голосов
/ 04 ноября 2011

Вы правы, что C ++ 03 не позволяет использовать тип с внутренней связью в качестве параметра типа шаблона, в то время как C ++ 11 делает это.

Однако я напоминаю, что определениявнутри анонимного пространства имен все еще есть внешняя связьэто имя

  • объекта, ссылки, функции или шаблона функции, который явно объявлен как статический, или,
  • объекта или ссылки, которые явно объявлены const и не объявлены явноextern и ранее не было заявлено о наличии внешней связи;или
  • член данных анонимного объединения.

Имя с областью пространства имен имеет внешнюю связь, если это имя

  • объекта илиссылка, если она не имеет внутренней связи;или
  • функция, если она не имеет внутренней связи;или
  • именованный класс (раздел 9) или безымянный класс, определенный в объявлении typedef, в котором класс имеет имя typedef для целей связывания (7.1.3);или
  • именованное перечисление (7.2) или неназванное перечисление, определенное в объявлении typedef, в котором перечисление имеет имя typedef для целей связывания (7.1.3);или
  • перечислитель, принадлежащий перечислению с внешней связью;или
  • шаблон, если это не шаблон функции с внутренней связью (пункт 14);или
  • пространство имен (7.3), если оно не объявлено в безымянном пространстве имен.

У вас есть именованный класс в области пространства имен, он имеет внешнюю связь.

И в сноске внизу страницы 115 ИСО / МЭК 14882: 2003 поясняется:

Хотя объекты в безымянном пространстве имен могут иметь внешнюю связь, они эффективно квалифицируются уникальным именемк их единице перевода и, следовательно, никогда не будет видно из любой другой единицы перевода.

Если у вас есть другая версия, попробуйте заглянуть в раздел 7.3.1.1 [namespace.unnamed]

4 голосов
/ 04 ноября 2011

Это недопустимый пример правила.Класс 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...