GDL 名前空間
GDL パーサーでは、同じ名前のテンプレートを複数回定義することはできません。 独立して作成された 2 つのテンプレート ファイルが誤ってテンプレートに同じ名前を使用してしまい、これらのテンプレート ファイルの両方を GDL ファイルに含めることができなくなる可能性があります。
名前の競合の問題を回避するために、GDL では名前空間がサポートされています。 ヘッダー ファイルの作成者は、定義全体を *DefineInNameSpace 構造内に囲むことによって、各テンプレートとマクロ定義がどの名前空間に属するかを指定できます。 この構成体のインスタンス名として指定されたシンボルは、囲まれたすべての定義が属する名前空間になります。 定義が 2 つ以上のネストされた *DefineInNameSpace 構造内に存在する場合、その定義は最も内側の *DefineInNameSpace 構造によって定義された名前空間にのみ属します。 定義が *DefineInNameSpace 構造内に存在しない場合、その定義は既定または「名前のない」名前空間に割り当てられます。
テンプレートまたはマクロ構造の本体を構成するエントリが別個の *DefineInNameSpace 構造内に囲まれている場合、パーサーはそれらの個々のエントリを新しい名前空間に配置しません。これは、個々のエントリが別個の定義ではないため、別の名前空間に存在できないためです。 ブロック マクロは入れ子になったマクロ定義を許可し、これらの入れ子になった定義を他の名前空間に割り当てることができます。 ただし、入れ子になった定義の名前空間を変更しても、その有効期間は延長されません。 入れ子になったマクロ定義は、それが定義された入れ子レベル内でのみ参照できます。
テンプレート名またはマクロ名は、名前空間内の修飾形式または非修飾形式で参照できます。 テンプレート名またはマクロ名を修飾するには、名前空間名の前にテンプレート名またはマクロ名の先頭にコロン文字 (たとえば、Namespace:MacroName など) が付きます。
注 *Template、*Macros、または *BlockMacro 定義の値として指定されたシンボル名は、名前空間で修飾できません。 定義の名前空間は、*DefineInNameSpace を使用してのみ定義できます。
たとえば、「TEMPNAME」という名前のテンプレートが「NSName」という名前の名前空間内で定義された後、次のコード例に示すように、そのテンプレートは名前空間修飾形式を使用して別のテンプレート定義から参照できます。
*DefineInNameSpace: NSName
{
*Template: TEMPNAME
{
*% member attributes
}
}
次のコード例に示すように、名前空間修飾構文を使用して、このテンプレートを別のテンプレートから参照できるようになりました。
*Template: ANOTHER_TEMPLATE
{
*Inherits: NSName:TEMPNAME
}
テンプレート参照の大部分が同じ名前空間を参照する場合、または 2 つ以上の名前空間内で参照されるテンプレート名間に名前の衝突がない場合は、名前空間修飾子を省略してテンプレート名のみを指定し、パーサーに依存してテンプレートを検索できます。一致するテンプレートが見つかるまで、名前空間の一覧を検索します。
名前空間の一覧は、*UsingNameSpace コンストラクト内の 1 つ以上の GDL エントリを囲むことで指定されます。 これらのエントリのいずれかがテンプレートまたはマクロへの非修飾参照を含む場合、それらの参照の解決は *UsingNameSpace コンストラクトの影響を受けます。 このコンストラクトのインスタンス名として指定されたシンボルは、検索する名前空間を識別します。
複数のコンストラクトを入れ子にすることで、複数の名前空間を指定できます。 検索順序は、最も内側の *UsingNameSpace 構造から始まり、外側に向かって進みます。 指定した名前空間でテンプレート定義が見つかった場合、検索は停止し、そのテンプレートが使用されます。 明示的に指定されたすべての名前空間が検索されても一致するものが見つからなかった場合、パーサーは、各囲みの *DefineInNameSpace 構造で名前が付けられた名前空間を最も内側の構造から外側に向かって検索します。 そして、その検索で参照を解決できない場合は、「名前のない」名前空間の検索を試みます。
注 名前空間の検索順序を外部の影響から隔離する必要がある場合は、参照の解決に必要なすべての名前空間を *UsingNameSpace 構造体を使用して指定する必要があります。
検索順序を確立するために *DefineInNameSpace 構造に依存しないでください。これは、ホストが追加の *UsingNameSpace 構造でインクルードされたファイルを囲む可能性があり、ホスト指定の名前空間が *DefineInNameSpace 構造によって名前が付けられた名前空間より前に検索されるためです。
たとえば、前に定義したテンプレートには、テンプレートの名前解決に使用するように明示的に指定された 2 つの名前空間が示されています。 *UsingNameSpace によって名前が付けられた名前空間は、*DefineInNameSpace によって以前に定義されている必要があります。 例外は「名前のない」名前空間で、常に存在し、NULL 記号で名前が付けられます。
次のコード例は、「名前のない」名前空間を指定して検索順序を定義する方法を示しています。
*UsingNameSpace: NSName2
{
*UsingNameSpace: *%%%%% omitting symbol specifies the Unnamed
*% Namespace.
{
*UsingNameSpace: NSName
{
*Template: ANOTHER_TEMPLATE
{
*Inherits: TEMPNAME
}
}
}
}
前述の例では、明示的に指定された名前空間内のすべての検索が失敗した後に「名前のない」名前空間が検索されますが、この例では、NSName2 名前空間の前に「名前のない」名前空間が検索されるように明示的に指定されています。
GDL データ エントリはテンプレート名を明示的に参照することはないため、*UsingNameSpace を使用しても、各データ エントリにどのテンプレートが割り当てられるかには影響しません。 ただし、*UsingNameSpace で指定された名前空間の検索順序 (最初の GDL データ エントリが解析される時点で有効) は、ROOT テンプレートの検索に使用されます。 1 つ以上の GDL ヘッダー ファイルを含める場合は、それらのヘッダー ファイルが誤ってデータ エントリを定義する最初のファイルにならないようにして、ROOT テンプレートを見つけるためにどの名前空間が使用されるかを決定する必要があります。
注 マクロ定義は、外側の入れ子レベルによってスコープが制限されます。 ただし、名前空間の入れ子レベルではマクロ定義のスコープが制限されません。マクロのスコープが、その名前空間の外部から見えるほど大きくない場合は、特定の名前空間に属するようにマクロを定義する必要がないためです。
名前空間コンストラクトは、他の種類のコンストラクト間でインターリーブできます。 名前空間構造がどこに現れるかについては、ほとんど制限がありません。 名前空間以外のコンストラクトは、名前空間の解決には影響しません。