5


1

この「宣言子が無効」になるのはなぜですか? C++

Vertex.hに頂点テンプレートがあります。 graph.hから:

20 template
21 class Vertex;

グラフテンプレートで使用します。

グラフ全体で頂点テンプレートを正常に使用し、頂点へのポインタを返すなどしています。 現在、初めてVertexオブジェクトを宣言およびインスタンス化しようとしていますが、gccから「宣言子」が「無効」であることが通知されています。 どうすればいいの?

81 template
82 Graph Graph::Dijkstra(vertex s, bool print = false) const
83 {
84    /* Construct new Graph with apropriate decorators */
85    Graph span = new Graph();
86    span.E.reserve(this->E.size());
87
88    typename Vertex v = new Vertex(INT_MAX);
89    span.V = new vector >(this->V.size,v);
90 };

そして、gccは言っています:

graph.h: In member function ‘Graph Graph::Dijkstra(Vertex, bool) const’:
graph.h:88: error: invalid declarator before ‘v’
graph.h:89: error: ‘v’ was not declared in this scope

これはおそらく別の初心者の質問であることは知っていますが、助けていただければ幸いです。

3 Answer


4


おそらくする必要があります

Vertex v = new Vertex(INT_MAX);

あなたは `Vertex`のインスタンスを宣言しているからです。 `typename`キーワードは、テンプレートパラメータリスト内でのみ有効です。

テンプレートパラメータリストの外での `keyword`の有効な使用を指摘してくれてありがとう* Abhay outis *。

コードをもう一度見た後、他の多くのことが思い浮かびます。

  1. * Mike Dinsdale *が指摘したように、テンプレートパラメータがありません ここ: new Vertex(INT_MAX);。 代わりに「頂点」を試してください。

  2. クラスインスタンスにポインターを割り当てています。 作成している場合 スタック上では、次のようになります。+ Vertex v(INT_MAX);

ヒープ上で作成する場合、 `v`はポインター型でなければなりません:

Vertex* v = new Vertex(INT_MAX);


1


イゴールは正しい。 次のエラーに関して:

graph.h:88: error: expected type-specifier before ‘Vertex’
  1. あなたはおそらく言う必要があります:

Vertex v = new Vertex(INT_MAX);


0


前述のように、それは最初に間違った `typename`の問題です。

いくつかの例:

template
struct MyClass
{
  struct Foo { static int MBar; };
};

template <>
struct MyClass { static int Foo; };

MyClassを使用する:

template
void useMyClass(T t)
{
  MyClass c;
}

あいまいさがないため、「typename」は必要ありません。コンパイラは、「MyClass」がここで型になることを知っています。

template
void useFoo(T t)
{
  typename MyClass::Foo f;
}

`Foo`シンボルが型、メソッド、属性のいずれであるかをコンパイラが事前に知らないため、明確にする必要があります。 実際、「T == int」の場合、「Foo」は「struct」ではなく「static」属性を表すため、このコードは誤りです!

void useFoo(int t)
{
  int f = MyClass::Foo;
}

void useFoo(float t)
{
  float f = MyClass::Foo::MBar;
}

ここで typename`は必要ありません:コンパイラはテンプレートパラメータリストのすべての型を知っているので、 MyClass`と `MyClass`のテンプレートクラスをインスタンス化でき、通常のクラスは各インスタンス化の裏返しを知っています(特に各シンボルが何を表すか)。

template
void useBar(T t)
{
  int i = typename MyClass::Foo::MBar;
}

「Foo」は型であり、コンパイラはそれを知る必要があるため、もう一度「typename」が必要です。

本当に得られなくても心配しないでください。 「typename」および「template」キーワードは、一般的なコードの異常な場所に忍び寄ることがあります。コンパイラエラーが始まるのを待つだけで、すぐにエラーの種類を記憶し、ウィンクで修正します。