Які простори імен є і які правила?


9

Зауважте: це питання про name space, а не namespace.

Стандарт C ++ має деякі посилання на це name space, але я не бачу визначення цього. У стандартах зазначено, що мітки та макроси знаходяться в різних просторах імен. Усі інші посилання на name spaceрозділ сумісності C / C ++, як це ( поточний проект ):

Це одна з небагатьох несумісностей між C і C ++, яку можна віднести до нового визначення простору імен C ++, де ім'я можна оголосити як тип і як не тип в єдиній області, що призведе до того, що ім'я нетипу приховує ім'я типу та вимагає, щоб ключові слова клас, структура, об'єднання чи enum використовувались для позначення імені типу. Це нове визначення простору імен забезпечує важливі нотаційні зручності для програмістів на C ++ та допомагає зробити використання визначених користувачем типів максимально подібним до використання основних типів.

Що це за нове визначення простору імен ? Де його можна знайти в стандарті? Які точні правила? Правила здаються складнішими, ніж "типи прихованих типів". Мовляв, це не компілюється:

typedef int Foo; // Foo is a type
void Foo();      // not a type, but compile error, instead of hiding

Але це робить:

struct Foo { }; // Foo is a type as well
void Foo();     // This hides the type Foo. "struct Foo" refers to the type

І це не компілює:

struct Foo { };   // Type
namespace Foo { } // Non-type, but compiler error instead of hiding

Практична думка полягає в тому, що простір імен - це однотонний клас із загальнодоступними членами (підкласи). Не пишіть мене :-)
peterh - Поновіть Моніку

2
@ peterh-ReinstateMonica прочитав запитання (знову)
YSC

FWIW, ваше посилання посилається на відповідні розділи: Під впливом підрозділу: [class.name] [див. Також [dcl.typedef]] Ви можете переглянути ці розділи, як правила працюють.
NathanOliver

Існує щонайменше два простори імен: одне для міток [stmt.label]/1та одне для макросів [cpp]/8.
YSC

1
Дещо цікаво (мені), що і опис, і приклад показують протилежне тому, що згадує обґрунтування; ім'я типу, яке приховує нетипове ім’я. З огляду на статус проекту, я б очікував, що цей пункт зміниться.
molbdnilo

Відповіді:


2

Термін простору імен може бути більш чітко встановлений у Стандарті ISO C; з посиланням на ISO C11 :

6.2.3 Проміжки імен ідентифікаторів

Якщо в одній точці одиниці перекладу видно більше однієї декларації певного ідентифікатора, синтаксичний контекст роз'єднує використання, що посилаються на різні сутності. Таким чином, існують окремі простори імен для різних категорій ідентифікаторів:

  • назви міток (розмежовуються синтаксисом декларації мітки та використання);
  • теги структур, об'єднань та перелічень (розчленованих відповідно до будь-яких32) ключових слів структура, об'єднання чи перерахування);
  • члени структур або спілок; кожна структура або союз має окремий простір імен для своїх членів (розмежований типом виразу, використовуваного для доступу до члена через оператор. або ->);
  • всі інші ідентифікатори, які називаються звичайними ідентифікаторами (декларуються у звичайних деклараторах або як константи перерахування).

Нове визначення простору імен з C ++, проте, ні в якій мірі недавнього часу , і був описаний в роботі [diff.class] / 1 в його нинішньому вигляді коли - або з моменту введення C ++ Стандарту ISO в '98 . Він коли-небудь згадується в будь-якій довжині в контекстах, для яких він відрізняється від ISO C, відповідно до [diff.class] / 1, який цитується ОП.

Для Afaics нам потрібно вдатися до ISO C11 / 6.2.3 та поєднати його з [diff.class] / 1 стандарту ISO C ++ для згуртованого та повного опису (нового) визначення простору імен C ++ , ніж ми бистимо ISO Стандарт C ++ для, наприклад, [basic.scope.hiding] , [class.name] / 2 , [stmt.label] / 1 , [cpp.replace] / 8 тощо, щоб дізнатися, як і де це застосовується.

[class.name] / 2

Оголошення класу вводить ім'я класу в область, де воно оголошено, і приховує будь-який клас, змінну, функцію чи інше оголошення цього імені в області, що додається. [...]

[stmt.label] / 1

[...] Мітки мають власний простір імен і не заважають іншим ідентифікаторам [...]

[cpp.replace] / 1

[...] Існує один простір для імен макросів. [...]


1

У C (6.2.3 пробіли імен ідентифікаторів) поняття пробілів імен визначається наступним чином.

1 Якщо в будь-якій точці одиниці перекладу видно більше однієї декларації певного ідентифікатора, синтаксичний контекст роз'єднує використання, що посилаються на різні сутності. Таким чином, існують окремі простори імен для різних категорій ідентифікаторів:

- імена міток (розмежовуються синтаксисом декларації та використання мітки);

- теги структур, об'єднань та перелічень (розчленованих слідом за будь-якими32) ключових слів структура, об'єднання чи перерахування);

- члени структур або спілок; кожна структура або союз має окремий простір імен для своїх членів (розмежований типом виразу, використовуваного для доступу до члена через оператор. або ->);

- всі інші ідентифікатори, що називаються звичайними ідентифікаторами (декларуються у звичайних деклараторах або як константи перерахування).

Так, наприклад, назва тегу структури може збігатися з назвою функції, оскільки вони належать до різних просторів імен. Коли ви вказуєте структуру з назвою тега структури, коли вам доведеться використовувати ключове слово struct. Так, наприклад, ці декларації не суперечать.

struct s
{
    int s;
};

void s( void );

struct s s1;

У цьому фрагменті коду назва тегу sструктури не суперечить імені функції, s оскільки ім'я тегу має бути вказане за ключовим словом struct.

У C ++ вам дозволяється використовувати назви тегів структури без ключового слова struct.

Наприклад

struct s
{
    int s;
};

s s;

- правильний код. У цій декларації

s s;

назва оголошеного ідентифікатора sприховує назву структури. Так, якщо тоді ви напишете, наприклад

s s1;

тоді компілятор видасть помилку, оскільки в цьому операторі s вважається ім'ям оголошеного вище ідентифікатора. Щоб вирішити неоднозначність, потрібно використовувати ключове слово структура

struct s
{
    int s;
};

s s;

struct s s1;

Це описано в наступній цитаті зі стандарту C ++ 20 (6.3.1 Деклараційні регіони та сфери застосування)

4 Дано набір декларацій в одному деклараційному регіоні, в кожному з яких вказується однакове некваліфіковане ім'я,

(4.1) - всі вони посилаються на одне ціле об'єднання або всі стосуються функцій та шаблонів функцій; або

(4.2) - саме одна декларація повинна оголошувати назву класу чи ім'я перерахування, що не є ім'ям typedef, а інші декларації мають посилатися на ту саму змінну, нестатичний член даних або перелік, або всі стосуються функцій та шаблонів функцій ; у цьому випадку ім'я класу або ім’я перерахування приховано (6.3.10). [ Примітка: Ім'я простори імен або ім'я шаблону класу повинно бути унікальним у своєму декларативному регіоні (10.3.2, пункт 17). - кінцева примітка ]

Як видно з цитати, ім'я простору імен повинно бути унікальним у своєму декларативному регіоні. Отже ці декларації

struct Foo { };
namespace Foo { } 

неправильні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.