Почему взлом структуры C не работает для объявлений шаблонов C ++? - PullRequest
4 голосов
/ 07 мая 2020

C имеет этот забавный прием, в котором одно имя может использоваться для объявления как типа, так и функции:

struct foo {};
void foo(void);

Теперь, каждый раз, когда я пишу foo, компилятор предполагает, что я имею в виду функция, если я не добавлю к ней префикс struct:

foo();  // call void foo(void)
struct foo bar;  // declare variable of type struct foo

Это отлично работает в C ++ даже с пространствами имен и вложенностью! Но это не работает с шаблонами:

template <typename> void bar(void);
template <typename> struct bar {};
// error: conflicting declaration of template struct bar
// previous declaration: template void bar()

Почему?

Мы уже имеем дело с устранителями неоднозначности в зависимых контекстах:

typename foo<A>::b();
foo<A>::template b<C>();

Не кажется большим натяжением применять обычные правила к неоднозначным именам шаблонов такого типа.

Предположим, для меня важно иметь такое же имя. Могу я как-нибудь заставить это работать?

Ответы [ 2 ]

4 голосов
/ 07 мая 2020

Почему?

Ответ находится в теле вопроса. Это работает для классов и функций, потому что в C есть отдельное пространство имен для тегов структуры и идентификаторов функций. Если C ++ нацелен на взаимодействие с кодом C, он должен сохранить это поведение. Достаточно взглянуть на такой API, как функция stat , принимающая аргумент struct stat, чтобы понять, почему C ++ сохранил достоверность такого кода. Эта работа с пространствами имен просто встроена в код C, находящийся в глобальном пространстве имен (поэтому ::stat и struct ::stat должны продолжать работать при необходимости).

Однако в C ++ идентификаторы тегов классов разделяют «пространство имен» с обычными идентификаторами. Таким образом, валидность этого «взлома» достигается с помощью специального случая в спецификации C ++, который просто скрывает классы, когда они конфликтуют.

[basi c .scope.hiding]

2 Имя класса или имя перечисления может быть скрыто именем переменной, члена данных, функции или перечислителя, объявленных в той же области. Если имя класса или перечисления и переменная, член данных, функция или перечислитель объявлены в одной и той же области (в любом порядке) с одним и тем же именем, имя класса или перечисления скрыто везде, где переменная, член данных, функция или Имя перечислителя видно.

Неважно, думали ли разработчики C ++ это хорошая или плохая идея. Существует устаревший код, который компиляторы C ++ должны по-прежнему принимать как действительный для облегчения взаимодействия с определенными системами.

Но нет устаревшего кода, работающего с шаблонами, который требует такого же поведения. Шаблоны - это полностью конструкция C ++ (не имеющая отношения к C). Таким образом, дизайн языка не имеет внешних ограничений, позволяющих добавить больше особых случаев для имен шаблонов. И это не так.

Предположим, для меня важно иметь такое же имя. Могу ли я как-нибудь заставить это работать?

На ум не приходит способ заставить это работать.

3 голосов
/ 08 мая 2020

Формулировка в temp.pre-7 :

Шаблон класса A не должен иметь то же имя, что и любой другой шаблон, класс, функция, переменная , перечисление, перечислитель, пространство имен или тип в той же области ([basi c .scope]), за исключением случаев, указанных в [temp.class.spec] ...

Ни одна из точек в temp.class.spe c не противоречит этому примеру.

Таким образом, в его нынешнем виде вы не можете иметь одно и то же имя для шаблона класса и шаблон функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...