一般に、テンプレート定義の外では、C++ での名前検索の規則では、名前が使用されるポイントの前に名前を宣言する必要があります。したがって、ほとんどの場合、あなたのアイデアは機能します。残念ながら、SebastianRedl が指摘したように、この経験則が適用されない特殊なケースがあります。
クラス定義内では、クラス (およびその外側のクラス) のすべてのメンバーの宣言は、メンバー関数 (ctor-initializer-list または exception-specification を含む) の本体内での名前検索中に表示されます。メンバー関数のデフォルト引数。
実例:
struct A
{
struct B
{
static void f(int i = M()) // uses 'A::M' declared later
{
A::f(); // calls A::f(int) declared later
}
};
static void f(void*)
{
f(); // calls A::f(int) declared later
}
static void f(int i = M()) // uses 'M' declared later
{
}
typedef int M;
};
変更されたトークンがメンバーの関数本体または既定の引数内にある場合は、トークンを囲むすべてのクラスを再解析する必要があります。
C++ ワーキング ドラフト標準 N3337 から:
3.4.1 非修飾名ルックアップ [basic.lookup.unqual]
関数の declarator-id に続くクラス X のメンバー関数 (9.3) の定義、またはクラス X の非静的データ メンバー (9.2) の波括弧または等号初期化子で使用される名前は、1 つの中で宣言されなければならない次の方法の:
— それが使用されているブロックまたは囲んでいるブロック(6.3)で使用される前、または
— クラス X のメンバーであるか、X の基本クラスのメンバーである (10.2)、または
— X がクラス Y (9.7) のネストされたクラスである場合、Y のメンバーであるか、Y の基底クラスのメンバーである必要があります (このルックアップは、最も内側の囲みクラスから始めて、Y の囲みクラスに順番に適用されます)。 、 また
— X がローカル クラス (9.8) またはローカル クラスのネストされたクラスである場合、クラス X の定義を囲むブロック内のクラス X の定義の前、または
— X が名前空間 N のメンバーである場合、または N のメンバーであるクラスのネストされたクラスである場合、またはローカル クラスまたは N のメンバーである関数のローカル クラス内のネストされたクラスである場合、名前空間 N または N を囲んでいる名前空間の 1 つでの名前の使用。