どのような名前空間があり、どのような規則がありますか?


9

注:この質問は、name spaceではなくについてnamespaceです。

C ++標準にはへの参照がいくつかありますがname space、これの定義はわかりません。標準では、ラベルとマクロは異なる名前空間にあると規定されています。への他のすべての参照name spaceは、このようにC / C ++互換性セクションにあります(現在のドラフト):

これは、CとC ++の間のいくつかの非互換性の1つであり、新しいC ++名前空間定義に起因する可能性があります。この場合、名前を単一のスコープ内でタイプおよび非タイプとして宣言して、非タイプ名で非表示にすることができます。タイプ名。キーワードclass、struct、unionまたは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

少なくとも2つの名前空間があります。1つはラベル用[stmt.label]/1、もう1つはマクロ用[cpp]/8です。
YSC

1
説明と例の両方が、その理論的根拠が述べているものの反対を示していることは(私にとって)多少興味深いです。非タイプ名を隠すタイプ名。ドラフトのステータスを考えると、そのパラグラフは変わると思います。
molbdnilo

回答:


2

名前空間の用語は、より多くのISO C標準で十分に確立することができます。ISO C11を引用:

6.2.3識別子の名前空間

特定の識別子の複数の宣言が翻訳単位の任意の時点で可視である場合、構文コンテキストは、異なるエンティティを参照する使用法を明確にします。したがって、次のように、識別子のさまざまなカテゴリに個別の名前空間があります。

  • ラベル名(ラベルの宣言と使用の構文によって明確化されています);
  • キーワードstruct、union、またはenumの構造体、共用体、および列挙型のタグ(any32に従うことで明確化)。
  • 構造または組合のメンバー; 各構造体または共用体には、そのメンバー用の個別の名前空間があります(。または->演算子を介してメンバーにアクセスするために使用される式のタイプによって明確になります)。
  • 通常の識別子と呼ばれる他のすべての識別子(通常の宣言子または列挙定数として宣言されます)。

ただし、C ++ の新しい名前空間の定義は、最近のことではなく、'98年のISO C ++標準の導入以来、現在の形式で[diff.class] / 1に記述されています。OPが引用する[diff.class] / 1のように、ISO Cとは異なるコンテキストでこれが長々と言及されることはありません。

ISO C11 / 6.2.3を使用し、それをISO C ++標準の[diff.class] / 1と組み合わせて、C ++の(新しい)名前空間定義のまとまりのある完全な説明を作成する必要があるAfaics、ISOを傷つけない[basic.scope.hiding][class.name] / 2[stmt.label] / 1[cpp.replace] / 8などのC ++標準。これがどのように、どこに適用されるかを確認します。

[クラス名] / 2

クラス宣言は、クラス名が宣言されているスコープにクラス名を導入し、その名前のクラス、変数、関数、またはその他の宣言を囲んでいるスコープに隠します。[...]

[stmt.label] / 1

[...]ラベルには独自の名前空間があり、他の識別子と干渉しません[...]

[cpp.replace] / 1

[...]マクロ名には1つの名前空間があります。[...]


1

C(6.2.3識別子の名前空間)では、名前空間の概念は次のように定義されています。

1特定の識別子の複数の宣言が翻訳単位の任意の時点で可視である場合、構文コンテキストは、異なるエンティティを参照する使用法を明確にします。したがって、次のように、識別子のさまざまなカテゴリに個別の名前空間があります。

—ラベル名(ラベルの宣言と使用の構文によって明確化されます)。

—キーワードstruct、union、またはenumの構造体、共用体、および列挙型のタグ(any32に従うことで明確化)。

—構造または組合のメンバー; 各構造体または共用体には、そのメンバー用の個別の名前空間があります(。または->演算子を介してメンバーにアクセスするために使用される式のタイプによって明確になります)。

—通常の識別子と呼ばれる他のすべての識別子(通常の宣言子または列挙定数として宣言されます)。

たとえば、構造タグ名は異なる名前空間に属しているため、関数名と一致する場合があります。キーワードを使用する必要があるときに、構造タグ名で構造を指定する場合struct。したがって、たとえば、これらの宣言は競合しません。

struct s
{
    int s;
};

void s( void );

struct s s1;

このコードスニペットでは、タグ名ss キーワードで指定する必要があるため、構造のタグ名は関数名と競合しませんstruct

C ++では、キーワードなしで構造タグ名を使用できますstruct

例えば

struct s
{
    int s;
};

s s;

正しいコードです。この宣言では

s s;

宣言された識別子のs名前は構造名を隠します。だから、あなたが例えば書こうとするなら

s s1;

このステートメントでは、sは上で宣言された識別子の名前と見なされるため、コンパイラはエラーを発行します。あいまいさを解決するには、キーワードstructを使用する必要があります

struct s
{
    int s;
};

s s;

struct s s1;

これについては、C ++ 20標準(6.3.1宣言領域とスコープ)の次の引用で説明されています。

4単一の宣言領域内の一連の宣言が与えられ、それぞれが同じ非修飾名を指定している、

(4.1)—それらはすべて同じエンティティを参照するか、またはすべてが関数と関数テンプレートを参照します。または

(4.2)— 1つの宣言だけがtypedef名ではないクラス名または列挙名を宣言し、他の宣言はすべて同じ変数、非静的データメンバー、または列挙子を参照するか、すべて関数および関数テンプレートを参照する; この場合、クラス名または列挙名は非表示になります(6.3.10)。[ 注:ネームスペース名またはクラステンプレート名は、宣言領域で一意である必要があります(10.3.2、17節)。—エンドノート ]

引用からわかるように、名前空間名はその宣言領域で一意である必要があります。したがって、これらの宣言

struct Foo { };
namespace Foo { } 

間違っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.