11.10 ARM C++ のネームスペース

テンプレートのインスタンス生成で名前のルックアップを行うときに、テンプレート定義のコンテキスト内で見つかる名前もあれば、テンプレートのインスタンス生成のコンテキスト内で見つかる名前もあります。

コンパイラには、以下の 2 つの異なるインスタンス生成ルックアップアルゴリズムが実装されています。
  • 標準で規定され、依存名ルックアップと呼ばれるアルゴリズム。
  • 依存名ルックアップが実装される前のアルゴリズム。
依存名ルックアップは、別のコマンドラインオプションで明示的にディセーブルに設定されていない限り、またはコンフィグレーションフラグとコマンドラインオプションのいずれかで依存名処理がイネーブルに設定されている場合に、厳密モードで実行されます。

依存名ルックアップ処理

コンパイラでは、依存名ルックアップを実行するときに、標準で規定されているインスタンス生成の名前ルックアップ規則を実装します。この処理では、クラス以外のプロトタイプのインスタンス生成を行う必要があります。そのため、標準で規定されている型名とテンプレートキーワードを使用してコードを記述することが必要です。

参照コンテキストを使用したルックアップ

コンパイラでは依存名ルックアップを使用しない場合、標準の 2 フェーズルックアップ規則に近い名前ルックアップアルゴリズムを使用します。ただし、ある意味では、これは既存のコードや既存のコンパイラとの互換性が高いアルゴリズムです。
テンプレートのインスタンス生成の一環として名前をルックアップし、そのインスタンス生成のローカルコンテキストで名前が見つからない場合は、統合されたインスタンス生成コンテキストでルックアップします。この統合されたインスタンス生成コンテキストには、テンプレート定義のコンテキストにある名前と、インスタンス生成のコンテキストにある名前の両方が含まれます。以下に例を示します。
namespace N
{
    int g(int);
    int x = 0;
    template <class T> struct A
    {
        T f(T t) { return g(t); }
        T f() { return x; }
    };
}
namespace M {
    int x = 99;
    double g(double);
    N::A<int> ai;
    int i = ai.f(0);        // N::A<int>::f(int) は N::g(int) を呼び出します
    int i2 = ai.f();        // N::A<int>::f() は 0 (= N::x) を返します
    N::A<double> ad;
    double d = ad.f(0);     // N::A<double>::f(double) は M::g(double) を呼び出します
    double d2 = ad.f();     // N::A<double>::f() も 0 (= N::x) を返します
}
テンプレートのインスタンス生成での名前のルックアップは、以下の点で、標準で規定されている規則に準拠しません。
  • テンプレート定義のコンテキストにある名前のみが関数ではない名前と見なされますが、ルックアップはテンプレートの定義時に参照できる名前に限定されません。
  • テンプレートが参照されるコンテキストにある関数は、そのテンプレート内のすべての関数呼び出しで考慮されます。参照コンテキストにある関数は、依存関数呼び出しにのみ参照されます。

引数依存ルックアップ

引数依存ルックアップがイネーブルになっているとき、引数依存ルックアップを使用して参照できる関数は、通常のルックアップで参照できる関数で多重定義できます。標準では、通常のルックアップで見つかった名前がブロック extern 宣言であってもこの多重定義を行うことが規定されています。この多重定義はコンパイラで行われますが、デフォルトモードでは、通常のルックアップでブロック extern が見つかると、引数依存ルックアップが抑制されます。
したがって、ネームスペースを使用していない場合でも、引数依存ルックアップを使ってコンパイルを行うかどうかによって、プログラムの動作が異なります。以下に例を示します。
struct A { };
A operator+(A, double);
void f()
{
    A a1;
    A operator+(A, int);
    a1 + 1.0;          // 引数依存ルックアップが有効な場合は operator+(A, double) を呼び出します
}                      // それ以外の場合は operator+(A, int); を呼び出します
非機密扱いPDF file icon PDF 版ARM DUI0472LJ
Copyright © 2010-2015 ARM.All rights reserved.