5

コードはGCCを使用してコンパイルされます。これはVC++でエラーなしで動作します

template <typename T>
void Function(T& A){

  T::iterator it; //Error : dependent-name 'T::iterator' is parsed as a non-type,
                  //but instatiation yields a type.
}

この記事では、コンパイラーは、型のイテレーターがTクラスであるか、単なる静的メンバーであるかを判断できないと述べています。したがってtypename、キーワードを使用してシンボルをタイプとして分類する必要があります。

私の質問は、Tコンパイル時に知られているので、コンパイラiteratorはTの内部がクラス(私の場合はTはvector<int>)であることをすでに知っているということです。では、なぜエラーがあるのでしょうか。

また、これはtypename、テンプレートパラメータの定義として使用する以外のキーワードの別の使用法ですT

アップデート:

私はここからすべての答えと他の答えを読みました。それは本当に私の考えすべてに答えました。私はそれをこれに要約することができます:

この権利を処理する正しいコンパイラはGccです。VC ++を使用すると、不正な形式のコードをコンパイルできます。Gccでのコンパイル中に発生するエラーは、構文解析によるものです。Gccは関数テンプレートのコードを解析しようとしますがT::iterator it;、Gcc by DeafaultがT::iterator変数として処理するため(T::iterator非タイプ)であり、タイプとしてではなく、この問題を解決するには、GccにT::iteratorタイプとして扱うように明示的に指示する必要があります。これは、キーワードを追加することによって行われtypenameます。
ここでVC++に戻ります。これが機能した理由の答えは、VC ++の既存のバグが原因であり、VC++がかどうかの決定を遅らせるかどうかです。T::iteratorは変数または型です。または、VC ++は、typename必要と思われる場所にキーワードを提供します。


役立つ記事
注:何か間違っていることがわかった場合は、UPDATEを自由に編集してください。

4

3 に答える 3

2

あなたが参照する記事は説明を提供します:

指定されたシンボルが実際にはタイプであり、特定のクラスの静的シンボルではないことをコンパイラーに通知する必要があります。

この記事の例を考えてみましょう:

class ContainsAType {
   class iterator { ... }:
   ...
};

class ContainsAValue {
   static int iterator;
};

したがって、Function()上記では、コンパイラT::iteratorは型変数か静的変数かを知る必要があります。このtypenameキーワードは、C++ のあいまいさを取り除きます。

于 2012-08-06T03:37:12.247 に答える
1

このスレッドには、同様のケースでの typename の使用に関するいくつかの良い議論が含まれています。

私の質問は、T はコンパイル時に既知であるため、コンパイラは T 内の反復子がクラスであることを既に認識しています (私の場合、T はベクトルです)。

はい、これが VC++ が typename キーワードなしで実行できる理由です。

では、なぜエラーが発生するのでしょうか。

標準では、テンプレート名の検索は 2 段階で行う必要があると規定されているためです。これには、場合によっては明確化が必要です (これを参照してください)。したがって、GCC は 2 フェーズの名前検索に関して標準に準拠しているため、GCC でエラーが発生します。一方、VC++ は遅延解析スキームを使用します。

DeadMG が指摘したように、VC++ のメソッドは、欠落している型名をコンパイラが診断できない場合、より複雑なコードで失敗する可能性があります。

このスレッドもチェックしてください。

于 2012-08-06T04:24:59.777 に答える
0

コンパイラが を見たとき、何がT::iterator it;何であるかはまだわかりTません。T関数を呼び出すとき(インスタンス化時間)にのみ何がわかるかがわかります。これは 2 フェーズの名前検索の一部です。最初のフェーズでは、コンパイラはFunction構文エラーの宣言をチェックし、すべての非依存名を検索します。これは、インスタンス化の時点まで待つのではなく、定義の時点でエラーを検出するのに役立ちます。

例えば:

template <typename T>
struct A
{
    X x;
};

struct X{};

int main()
{
    A<int> a;
}

優れたコンパイラは、検索Xして、それが何であるかを知らないことを伝えます。ただし、MSVC コンパイラはこの不正なコードを受け入れます。

別の例を次に示します。

template <typename T>
class A : public I_do_not_exist
{
};

優れたコンパイラはI_do_not_exist、存在しないことを通知します (MSVC はこのコードをコンパイルします)。

于 2012-08-06T04:32:41.683 に答える