3

次のコードが正常にコンパイルされることがわかっています。

void f() {}
void g(void) {}

f();
g();

しかし、なぜ次のことはできませんか。

template<typename T>
void f() {}

template<typename T>
void g(T) {}

f<void>();  //ok
g<void>();  //error

g<void>() 行でエラーが発生するのはなぜですか?

エラー: 'g()' の呼び出しに一致する関数がありません

void型引数としてインスタンス化できないのはなぜですか? 関数テンプレートが次のようにインスタンス化されない理由:

void g(void) {}  //to be instantiated from the function template

結局、それは私が求めたものです。

私は権威ある答えを探しています。

4

2 に答える 2

5

合法的な議論は、それvoidは完成できない不完全な型であるため、最上位の型として使用することは決してできないということです。と比較してくださいvoid a;void引数リストの in は型ではなく、引数がないことを示す規則であるため、これは少し混乱します。

于 2012-09-08T16:34:48.500 に答える
3

C 互換構文ハック

以下:

void f() {}
void g(void) {}

f();
g();

C との互換性のために保持されている問題のある C++ 構文表記法、つまりvoidin g:のためだけにコンパイルされます。

void g(void) {}

ここでは、「パラメーターなし」と言うために使用され、予想される「型の 1 つのパラメーター」ではありvoidません (これは意味がありません)。

C++ では、C ヘッダーをインクルードする必要がある場合があるため、この表記がサポートされていないと問題が発生します。ただし、C++ コードで使用する必要があるという意味ではありません。

C++ テンプレート

宣言する場合:

template<typename T>
void g(T) {}

タイプ T の名前のないパラメーターを 1 つ持つg、タイプ でテンプレート化された関数を宣言しています。T

したがって、 がTの場合、タイプ の名前のないパラメーターが 1 つvoidある関数をまだ使用しています。これは意味がありません。これは、コンパイラが文句を言うことを意味します。gvoid

解決?

真剣に?

表記は一切使用しないでくださいg(void)。これは、C++ で構造体を typedef するようなものです。これは役に立たず、コードを難読化するだけです。

解決策2?

さて、実際に次のコードがある場合:

template<typename T>
void g(T) {}

g()実装を提供したい場合は、オーバーロードを提供する必要があります。

// Original template
template<typename T>
void g(T) { /* implementation for the generic case */ }

// Code to handle g()
void g()  { /* implementation for the specific "void" case */ }

また、g<void>()実装を提供する場合は、特殊化によって void ケースを処理するテンプレート化されたオーバーロードを提供する必要があります。

// Original template
template<typename T>
void g(T)      { /* implementation for the generic case for g(T) */ }

// Code to handle g<void>()
template<typename T>
void g()       { /* implementation for the generic case for g() */ }

template<>
void g<void>() { /* implementation for the generic case for g<void>() */ }
于 2012-09-08T17:07:39.723 に答える