Hangi isim alanları var ve kurallar neler?


9

Not: Bu soru hakkında name space, değil namespace.

C ++ standardının bazı referansları vardır name space, ancak bunun tanımını görmüyorum. Standartlar, etiketlerin ve makroların farklı ad alanlarında olduğunu söylüyor. Diğer tüm referanslar name spaceşu şekilde C / C ++ uyumluluk bölümünde ( mevcut taslak ):

Bu, C ve C ++ arasında , bir adın tür olarak ve tür olmayan adın gizlenmesine neden olan tek bir kapsamda türsüz olarak bildirilebildiği yeni C ++ ad alanı tanımına atfedilebilecek birkaç uyumsuzluktan biridir. tür adı ve sınıf, yapı, birleşim veya enum anahtar sözcüklerinin tür adını belirtmek için kullanılmasını gerektirir. Bu yeni ad alanı tanımı , C ++ programcılarına önemli gösterim kolaylığı sağlar ve kullanıcı tanımlı türlerin, temel türlerin kullanımına mümkün olduğunca benzer şekilde kullanılmasına yardımcı olur.

Bu yeni ad alanı tanımı nedir? Standartta nerede bulabilirim? Kesin kurallar nelerdir? Kurallar, "tür olmayan gizleme türleri" nden daha karmaşık görünmektedir. Mesela bu derlenmiyor:

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

Ancak bu:

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

Ve bu da derlenmiyor:

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

Pratik görüş, bir ad alanının herkese açık üyelere (alt sınıflara) sahip tek bir sınıf olmasıdır. Lütfen linç etmeyin :-)
peterh - Monica

2
@ peterh-ReinstateMonica soruyu okudu (tekrar)
YSC

FWIW, bağlantınız ilgili bölümlere bağlanıyor : Etkilenen alt madde: [class.name] [ayrıca bkz. [Dcl.typedef]] Kuralların nasıl çalıştığına ilişkin bölümleri görebilirsiniz.
NathanOliver

En az iki ad alanı vardır: biri etiketler [stmt.label]/1ve diğeri makrolar için [cpp]/8.
YSC

1
Gerek açıklama gerekse de örneğin gerekçenin bahsettiğinin tam tersini göstermesi (benim için) biraz ilginçtir; tür olmayan bir adı gizleyen bir tür adı. Taslak durumu göz önüne alındığında, bu paragrafın değişmesini beklerdim.
molbdnilo

Yanıtlar:


2

Adı uzay terimi daha ISO C Standardı köklü olabilir; ISO C11'e atıfta bulunarak :

6.2.3 Tanımlayıcıların isim alanları

Bir çeviri birimindeki herhangi bir noktada belirli bir tanımlayıcının birden fazla bildirimi görünürse, sözdizimsel bağlam farklı varlıkları ifade eden kullanımları belirsizleştirir. Bu nedenle, çeşitli tanımlayıcı kategorileri için aşağıdaki gibi ayrı ad alanları vardır:

  • etiket adları (etiket beyanı ve kullanımının sözdizimi ile netleştirilmiştir);
  • struct, union veya enum anahtar kelimelerinin yapıları, birlikleri ve numaralandırmalarının (any32'yi izleyerek anlamsızlaştırılmış) etiketleri;
  • yapıların veya sendikaların üyeleri; her yapı veya birleşimin üyeleri için ayrı bir ad alanı vardır (üyeye. veya -> operatörü aracılığıyla erişmek için kullanılan ifadenin türüne göre ayrılmış);
  • sıradan tanımlayıcılar olarak adlandırılan diğer tüm tanımlayıcılar (sıradan bildirimlerde veya numaralandırma sabitleri olarak bildirilir).

Bununla birlikte, C ++ ' ın yeni ad alanı tanımı hiçbir zaman yeni değildir ve ISO C ++ Standardının '98'e girişinden bu yana [diff.class] / 1 içinde şu anki haliyle tanımlanmıştır . OP tarafından belirtilen [diff.class] / 1 uyarınca ISO C'den farklı olduğu bağlamlarda sadece herhangi bir uzunlukta bahsedilmiştir.

Afaics, C ++ (yeni) ad alanı tanımının tutarlı ve eksiksiz bir açıklaması için ISO C11 / 6.2.3'e başvurmalı ve ISO C ++ Standardının [diff.class] / 1'i ile birleştirmeliyiz , C ++ Standardı, örneğin [basic.scope.hiding] , [class.name] / 2 , [stmt.label] / 1 , [cpp.replace] / 8 ve benzerlerinin nasıl ve nerede geçerli olduğunu görmek için.

[Class.name] / 2

Sınıf bildirimi, sınıf adını bildirildiği kapsama sokar ve bir kapalı kapsamda bu adın herhangi bir sınıfını, değişkenini, işlevini veya başka bir bildirimini gizler. [...]

[Stmt.label] / 1

[...] Etiketlerin kendi isim alanları vardır ve diğer tanımlayıcılarla karışmazlar [...]

[Cpp.replace] / 1

[...] Makro isimleri için bir isim alanı var. [...]


1

C'de (6.2.3 Tanımlayıcıların isim uzayları) isim uzayları kavramı aşağıdaki şekilde tanımlanır.

1 Bir çeviri birimindeki herhangi bir noktada belirli bir tanımlayıcının birden fazla bildirimi görünürse, sözdizimsel bağlam farklı varlıkları ifade eden kullanımları belirsizleştirir. Bu nedenle, çeşitli tanımlayıcı kategorileri için aşağıdaki gibi ayrı ad alanları vardır:

- etiket adları (etiket beyanı ve kullanımının sözdizimi ile netleştirilmiştir);

- struct, union veya enum anahtar kelimelerinin yapılarının, sendikalarının ve numaralandırmalarının (any32'yi izleyerek ayrıştırılmış) etiketleri;

- yapıların veya sendikaların üyeleri; her yapı veya birleşimin üyeleri için ayrı bir ad alanı vardır (üyeye. veya -> operatörü aracılığıyla erişmek için kullanılan ifadenin türüne göre ayrılmış);

- sıradan tanımlayıcılar olarak adlandırılan diğer tüm tanımlayıcılar (sıradan bildirimlerde veya numaralandırma sabitleri olarak bildirilir).

Örneğin, bir yapı etiketi adı, farklı ad alanlarına ait oldukları için bir işlev adıyla çakışabilir. Anahtar kelimeyi kullanmanız gerektiğinde yapı etiketi adına sahip bir yapı belirttiğinizde struct. Örneğin bu bildiriler çelişmez.

struct s
{
    int s;
};

void s( void );

struct s s1;

Bu kod snippet'inde, etiket adı anahtar sözcükle belirtileceğinden, yapının etiket adı sişlev adıyla çakışmaz .sstruct

C ++ 'da, anahtar sözcük olmadan yapı etiketi adlarını kullanmanıza izin verilir struct.

Örneğin

struct s
{
    int s;
};

s s;

doğru bir koddur. Bu beyanda

s s;

bildirilen tanımlayıcının sadı yapı adını gizler. Eğer öyleyse örneğin yazacaksınız

s s1;

bu deyimde yukarıda bildirilen tanımlayıcının adı olarak kabul edildiğinden derleyici bir hata verir. Belirsizliği gidermek için struct anahtar kelimesini kullanmanız gerekir

struct s
{
    int s;
};

s s;

struct s s1;

Bu, C ++ 20 Standardından (6.3.1 Beyan alanları ve kapsamları) aşağıdaki alıntıda açıklanmıştır.

4 Her biri aynı niteliksiz adı belirten tek bir bildirim bölgesinde bir dizi bildirim verildiğinde,

(4.1) - hepsi aynı varlığa veya hepsi işlevlere ve işlev şablonlarına atıfta bulunacaktır; veya

(4.2) - tam olarak bir beyanname, typedef adı olmayan bir sınıf adı veya numaralandırma adı bildirir ve diğer bildirimlerin tümü aynı değişken, statik olmayan veri üyesi veya numaralandırıcıya veya tümü işlevlere ve işlev şablonlarına başvurur ; bu durumda sınıf adı veya numaralandırma adı gizlenir (6.3.10). [ Not: Bir ad alanı adı veya bir sınıf şablonu adı bildirim bölgesinde benzersiz olmalıdır (10.3.2, Madde 17). - son not ]

Alıntıdan da görebileceğiniz gibi, bir ad alanı adının bildirim bölgesinde benzersiz olması gerekir. Yani bu açıklamalar

struct Foo { };
namespace Foo { } 

yanlış.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.