4

g++ 4.6 でコンパイルされた次のプログラムでは、エラーが発生します。

request for member ‘y’ in ‘a2’, which is of non-class type ‘A<B>(B)’

その最後の行で:

#include <iostream>

template <class T> class A
{
public:
  T y;
  A(T x):y(x){}
};

class B
{
public:
  int u;
  B(int v):u(v){}
};

int main()
{
  int v = 10;
  B b1(v);

  //works
  A<B> a1(b1);

  //does not work (the error is when a2 is used)
  A<B> a2(B(v));

  //works
  //A<B> a2((B(v)));

  std::cout << a1.y.u << " " << a2.y.u << std::endl;    
}

コードに含まれる動作中のバリアントからわかるように、A のコンストラクターの引数の周りに括弧を追加すると、問題が解決します。

コンストラクターの呼び出しを関数宣言として解釈することによって引き起こされる関連エラーをいくつか見てきました。たとえば、コンストラクターへの引数を持たずに中括弧を使用してオブジェクトを作成する場合などです。

myclass myobj();

しかし、私にはそう思われます

A<B> a2(B(v));

関数宣言として解釈できません。

誰かが私に何が起こっているのか説明できますか?

4

4 に答える 4

8

これは、コンパイラが関数の宣言として解釈する最も厄介な解析のケースです。A<B> a2(B(v))そのような:

A<B>は戻り値の型
a2です は関数名
Bです は引数の型です
vは引数の名前です

だから、あなたがやっているとき

std::cout << a1.y.u << " " << a2.y.u << std::endl;

コンパイラはa2.y.uクラスとは見なさないため、non-class typeエラーが発生しています。

また、関数宣言では二重括弧が許可されてA<B> a2((B(v)));いないため、コンパイラはそれを関数宣言としてではなく、変数宣言として解釈するため、バージョンは機能します。

于 2012-06-21T12:54:55.077 に答える
2

「最も厄介な解析」に少し慣れていると思います。つまりA<B> a2(B(v));、変数宣言ではなく関数宣言として解析されています。

于 2012-06-21T12:54:39.447 に答える
2

次のコード サンプルに示すように:

int a (int(v)) {
    return v;
}

int main() {
    std::cout << a(5); //prints 5
}

その行は確かに宣言です。この例では、パラメーターの型intと名前はvです。あなたのコードに関連して、パラメータは型Bであり、名前が付けられてvいます。これが、二重括弧を使用したときに同様の動作が得られる理由です: それは同じことだからです!

于 2012-06-21T12:54:39.653 に答える
2

これは関数宣言です:

A<B> a2(B(v));
//is same as:
A<B> a2(B v);

//consider:
int foo(int v);
int foo(int (v));
于 2012-06-21T12:55:45.100 に答える