3

今日、私は今まで見たことのない2つのエラーメッセージに出くわしました。それは私にとって全く新しいことです。

コードは次のとおりです。

template<typename T>
struct adder { adder(const T &item) { } };

template<typename T>
void initializer(const T &item) {  adder<T>(item); }

int main() 
{
   initializer("const string literal");
}

コンパイル時に、GCCは次のエラーを出します。

prog.cpp:関数内'void initializer(const T&)':
prog.cpp:6:エラー:'adder <T>アイテム'の宣言がパラメータをシャドウします
prog.cpp:関数内' void initializer(const T&)[with T = char [21]]':
prog.cpp:10:ここからインスタンス化
prog.cpp:6:エラー:' adder <char [21]> item'の宣言がパラメーターをシャドウします
prog.cpp:6:エラー:いいえ'adder <char [21]> :: adder()' </ strong>
prog.cpp:3:注:候補は次のとおりです:adder <T> :: adder(const T&)[with T = char [21]]
prog.cpp:3:注:adder <char [21]> :: adder(const adder <char [21]>&)


太字のテキストを参照してください。1つのエラーが2回表示されます。これは

エラー:'<strong> adder <T> item 'の宣言がパラメーターをシャドウします
エラー:' adder <char [21]>item 'の宣言がパラメーターをシャドウします

どういう意味ですか?異なるテンプレート引数で2回表示されるのはなぜですか?最初のものはT、2番目のものはchar [21]

編集:名前アイテムadder<T>(item)で変数を宣言しますか?しかし、それは私が意図したものではありません。コンストラクターへの引数としてアイテムを渡す一時オブジェクトを作成する必要があると思います。

この問題を扱っている規格のセクションを知りたいです!


他の興味深いエラーはこれです:

エラー:'adder <char [21]> :: adder()'</p>の呼び出しに一致する関数がありません

これは、コンパイラがデフォルトのコンストラクタを探していることを示していますか?しかし、実際には私のコードが6行目でそれを使用していないのに、なぜコンパイラがそれを探しているのか疑問に思っています。


ideoneのコード:http ://www.ideone.com/jrdLL

4

4 に答える 4

4

これは、コンパイラがデフォルトのコンストラクタを探していることを示していますか?しかし、実際には私のコードが6行目でそれを使用していないのに、なぜコンパイラがそれを探しているのか疑問に思っています。

コンパイラは、名前itemを使用してローカル変数を宣言すると考えているためです。

http://codepad.org/YBPKCvmm

于 2011-03-14T11:17:30.463 に答える
3

何が起こっているのかを理解するための鍵は、次のことを理解することです。adder(item); itemという名前のローカル変数の定義であり、型加算器を持っています。括弧は不要ですが、完全に許容されます。コンストラクターを呼び出したい場合は、データ定義として解釈できない方法でコンストラクターを記述して、曖昧さを解消する必要があります。たとえば、次のようになります。adder((item)); (これがどのように使用されるかはわかりません。加算器の一時オブジェクトを作成し、式の最後でそれを破棄します。)

ステートメントがデータ宣言として理解されると、実際のエラーメッセージはclear(er)になります。関数パラメーターは、関数の最上位ブロックで定義されているかのように扱われるため、adder(item)は重複しています(矛盾しています)。定義、およびadderにはデフォルトのコンストラクターがないため、引数を指定せずにそのインスタンスを定義することはできません。

于 2011-03-14T11:23:52.933 に答える
3

現時点ではC++0xドラフトにしかアクセスできないため、現在の章と節をお伝えすることはできませんが、あまり変わっていないと思います。0xでは、セクション6.8にあります-あいまいさの解決:

式ステートメントと宣言を含む文法にはあいまいさがあります。左端の部分式として関数スタイルの明示的な型変換(5.2.3)を使用する式ステートメントは、最初の宣言子が(。そのような場合、ステートメントは宣言です。

[...]

T(a); // declaration

つまり、タイプTの「a」という名前の変数の宣言です。

adder<T>(item)一時的な(名前のない)オブジェクトを定義する場合、それは式ステートメントになりますが、宣言ステートメントまたは式ステートメントのいずれかとして解析できる場合、C++はそれを宣言ステートメントとして解析します。

[...]解決策は、宣言である可能性のある構成を宣言と見なすことです。(8.2)

言い換えれば、それはみんなの親愛なる旧友、最も厄介なパースのいとこです。

更新: C ++ 03のあいまいさの解決を調べましたが、これらの箇所は同じです。

于 2011-03-14T15:24:52.887 に答える
1

「シャドウイング」とは、2つのオブジェクトが同じ名前を持っていることを意味します。この名前は、現時点では言語で許可されていますが、意図されていない可能性があります。

于 2011-03-14T11:18:12.193 に答える