関数テンプレートのインスタンス化で関数宣言構造体を使用することは許可されていないため、関数内に関数構造体を定義することは許可されていません。
知っておくべき他の重要な落とし穴はありますか?たとえば、これは悪いことです:
int foo()
{
struct Scratch
{
int a, b, c;
};
std::vector<Scratch> workingBuffer;
//Blah Blah
}
1. C ++標準では、テンプレートでローカルに定義されたクラスを使用することは禁止されています。
14.3.1 / 2:ローカル型、リンケージのない型、名前のない型、またはこれらの型のいずれかから複合された型は、テンプレート型パラメータのテンプレート引数として使用してはなりません。
コード例:
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as
// template-argument
X<S*> x4; // error: pointer to local type
// used as template-argument
}
IBMの資料からもう少し参考資料を示します。
2.ローカルクラスの宣言では、型名、列挙、囲んでいるスコープの静的変数、および外部変数と関数のみを使用できます。
コード例:
int x; // global variable
void f() // function definition
{
static int y; // static variable y can be used by
// local class
int x; // auto variable x cannot be used by
// local class
extern int g(); // extern function g can be used by
// local class
class local // local class
{
int g() { return x; } // error, local variable x
// cannot be used by g
int h() { return y; } // valid,static variable y
int k() { return ::x; } // valid, global x
int l() { return g(); } // valid, extern function g
};
}
int main()
{
local* z; // error: the class local is not visible
return 0;
}
3.ローカルクラスに静的データメンバーを含めることはできません
コード例:
void f()
{
class local
{
int f(); // error, local class has noninline
// member function
int g() {return 0;} // valid, inline member function
static int a; // error, static is not allowed for
// local class
int b; // valid, nonstatic variable
};
}
ローカルクラスのスコープは、それらが定義されている関数ですが、それ自体は興味深いものではありません1。
ローカルクラスが興味深いのは、それらが何らかのインターフェイスを実装している場合、(を使用して)そのインスタンスを作成してnew
返すことができるため、関数の外部でも基本クラスポインタを介して実装にアクセスできることです。
ローカルクラスに関するその他の事実:
静的メンバー変数を定義することはできません。
それらは、囲んでいる関数の非静的な「自動」ローカル変数にアクセスできません。しかし、彼らはstatic
変数にアクセスできます。
テンプレート関数で使用できます。ただし、テンプレート引数として使用することはできません。
テンプレート関数内で定義した場合は、囲んでいる関数のテンプレートパラメーターを使用できます。
ローカルクラスはfinalです。つまり、関数外のユーザーはローカルクラスから関数に派生できません。ローカルクラスがない場合は、名前のない名前空間を別の翻訳単位に追加する必要があります。
ローカルクラスは、通常サンクと呼ばれるトランポリン関数を作成するために使用されます。
標準(2003)からのいくつかの参照
\1。クラスは関数定義内で定義できます。このようなクラスはローカルクラスと呼ばれます。ローカルクラスの名前は、それを囲むスコープに対してローカルです。ローカルクラスは、囲んでいるスコープのスコープ内にあり、囲んでいる関数と同じように、関数の外部の名前にアクセスできます。ローカルクラスの宣言では、型名、静的変数、外部変数と関数、および囲んでいるスコープの列挙子のみを使用できます。
[Example:
int x;
void f()
{
static int s ;
int x;
extern int g();
struct local {
int g() { return x; } // error: x is auto
int h() { return s; } // OK
int k() { return ::x; } // OK
int l() { return g(); } // OK
};
// ...
}
local* p = 0; // error: local not in scope
—end example]
\2。囲み関数には、ローカルクラスのメンバーへの特別なアクセス権はありません。通常のアクセスルール(11節)に従います。ローカルクラスのメンバー関数は、定義されている場合は、クラス定義内で定義されるものとします。
\3。クラスXがローカルクラスの場合、ネストされたクラスYはクラスXで宣言され、後でクラスXの定義で定義されるか、後でクラスXの定義と同じスコープで定義されます。ローカルクラス内にネストされたクラスはローカルクラス。
\4。ローカルクラスには静的データメンバーを含めないでください。
ローカル構造体/クラスは静的データメンバーを持つことができず、静的メンバー関数のみを持つことができます。また、テンプレートにすることはできません。
ローカル構造体は、C++98でも完全に合法です。ただし、C ++ 98ではテンプレートで使用できませんが、C++0xでは使用できます。g ++ 4.5は、-std = c++0xモードのテンプレートでローカル構造体を使用することをサポートします。
はい。C ++ 03では、ローカルクラスをテンプレートパラメータとして使用することはできません。