c++ - テンプレートに関するこの記事の理解に助けが必要

c++ templates

私はこのpageからこの記事を読んでいたので、コードを提示しましょう。

template <class T> class D: typename C<T>::Base { //#1 error
    D(): typename C<T>::Base(typename C<T>::Base(0)) { } //#2 error, #3 correct
    typename C<T> f() { //#4 error
        typename C<T>::A* p; //#5 correct
        A<T>::B * n;
    }
};
class Q{
    typename C<long>::A * p; // #6 error
}
template <class T, class U> class R{
    typename C<long>::A * p; // #7 optional
}


#3は正しいですが、著者が伝えようとしていることを理解しようとしています。彼は言う:


タイプ名#3:正解。ここでは、typenameを使用して、
パラメータのタイプ。タイプ名がない場合、式C::Base(0)
Baseと呼ばれる関数の呼び出しとして扱われます。とともに
typenameプレフィックス、C::Base(0)は、タイプの一時オブジェクトを作成します
C::Baseは引数0で初期化されます。


また、その部分の少し上を見ると、作者はこう言っています:


typenameキーワードは、従属名の前に付ける必要があります。
次の3つのルールを満たします。

1.テンプレート内に表示されます

2.それは修飾されています//この引用の最初の段落と合わせてこの行をまったく理解できません

3.基本クラスの仕様やメンバーの初期化では使用されません
リスト。


この引用の最初の段落と合わせて、この行(上記の#2)をまったく理解できません。著者の意味を説明できますか?
答え
「修飾」とは、同じスコープではなく、現在のスコープのサブスコープであり、テンプレートにも依存することを意味します。例えば、

template <class T> struct C {
    typedef int b;
}


bは、別のテンプレートで参照される場合、修飾されたidです。

template<typename T> struct M {
    typename C<T>::b bb;
}


標準からの関連引用(§14.6.3):


タイプを参照する修飾ID。
ネストされた名前指定子は、テンプレートパラメータ(14.6.2)に依存します。
修飾IDであることを示すために、キーワードtypenameを前に付ける
タイプを示し、精巧なタイプ指定子(7.1.5.3)を形成します。


そして§14.6.2:

A name used in a template declaration or definition and that is dependent on a template-parameter is
assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified
by the keyword typename. [Example:
    // no B declared here
    class X;
    template<class T> class Y {
        class Z; // forward declaration of member class
        void f() {
            X* a1; // declare pointer to X
            T* a2; // declare pointer to T
            Y* a3; // declare pointer to Y<T>
            Z* a4; // declare pointer to Z
            typedef typename T::A TA;
            TA* a5; // declare pointer to T’s A
            typename T::A* a6; // declare pointer to T’s A
            T::A* a7; // T::A is not a type name:
            // multiply T::A by a7; ill-formed,
            // no visible declaration of a7
            B* a8; // B is not a type name:
            // multiply B by a8; ill-formed,
            // no visible declarations of B and a8
        }
    };
—end example]


そして§14.6.7:

Within the definition of a class template or within the definition of a member of a class template, the keyword
typename is not required when referring to the unqualified name of a previously declared member
of the class template that declares a type. The keyword typename shall always be specified when the
member is referred to using a qualified name, even if the qualifier is simply the class template name.
[Example:
    template<class T> struct A {
        typedef int B;
        A::B b; // ill-formed: typename required before A::B
        void f(A<T>::B); // ill-formed: typename required before A<T>::B
        typename A::B g(); // OK
    };

The keyword typename is required whether the qualified name is A or A<T> because A or A<T> are synonyms
within a class template with the parameter list <T>. ]
関連記事

c++ - 循環呼び出しを検出する方法は?

c++ - セグメンテーション違反と実行時エラー[重複]

c++ - NVCCにx64オブジェクトを生成するように指示するにはどうすればよいですか?

c++ - LuaPlus Metatablesの初心者向け質問

c++ - 明示的な型変換の要件

c++ - ペアベクトルc++の上限

c++ - setjmpがスタックを保存しないのはなぜですか?

c++ - coutをキャプチャして関数にリダイレクトする

c++ - Eclipseを使用してMySQLをC++に接続しますか?

c++ - C++用のどのXSLTプロセッサーですか?