2012-02-03 16 views
1

私はこのURLTがテンプレートの引数である場合、文T :: x(y)はあいまいですか?

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fkeyword_typename.htm

でファクトシートを読んでいたと私はT :: xが可能表すことができますどのような種類が分からないことに気づきました。ここで抜粋

template<class T> class A 
{ 
    T::x(y); 
    typedef char C; 
    A::C d; 
} 

は、文Tである:: X(y)はあいまいです。非ローカル引数yを持つ関数x() の呼び出しか、T :: x型の変数y の宣言になります。 C++はこの文を関数呼び出しとして解釈します。 コンパイラがこのステートメントを 宣言として解釈するには、キーワードのtypenameを の先頭に追加します。ステートメントA :: C d;形成されていない。クラスAも Aを参照しており、したがってテンプレートパラメータに依存します。あなたは、この宣言の先頭に キーワード型名を追加する必要があります。

私は型T :: xの変数yがあるかもしれない方法を理解したいと思います

、この作品とは、これはおそらく何をどのように意味するかもしれませんでしょうか? xは何ですか?私の完全な答えにウォームアップとして

答えて

6

:-)

おかげで、次の点を考慮してください

ここ
template <typename T> void IterateOverContainer(T container) { 
    /* Error! */ 
    T::iterator itr(container.begin()); 
} 

iteratorTの内部にネストタイプです。例えば、std::vector<int>::iteratorです。ここではあいまいさを避けるために、typenameキーワードが必要になる:

template <typename T> void IterateOverContainer(T container) { 
    /* Now good! */ 
    typename T::iterator itr(container.begin()); 
} 

は今、これは「明確に」タイプの名前が(それは何typename手段だ!)され、我々はコールではなく、変数を宣言したいこと、それは明らかですので、機能。

template <typename T> void IterateOverContainer(T container) { 
    auto itr(container.begin()); 
} 

あるいは、より明確に:

あなたの質問にとして今
template <typename T> void IterateOverContainer(T container) { 
    auto itr = container.begin(); 
} 

、:どのように新しいC++ 11個の機能で、あなたはautoで完全にこれを回避することができ、言っ

T::x(y)は変数を宣言できますか?

template <typename T> void IterateOverContainer(T container) { 
    /* Error! */ 
    T::iterator(itr); 
} 
:私たちはこのような何かを持っていた場合

int (x); 

そう

int x; 

と同じです:まあ、原因Cの奇妙な癖に、これは完全に合法変数の宣言であります

これは、タイプT::iteratoritrという名前の変数の宣言として、またはT::iteratorを呼び出してitrを呼び出すと解釈できますパラメータ。 typenameを使用すると、どちらが曖昧なのかが明確になります。

興味深いことに、この余分な括弧は、Most Vexing Parseが存在するのと同じ理由です。あなたは決してそれに遭遇しないことを願っています:-)

これは役に立ちます。

+0

あなたのアカウントはこの質問に答えるように見えます:) –

+0

もう少し簡単な質問です。別のクラス(Yの中のx)を定義すると、Y :: xという型ですか?私は、小文字のxは私を捨てたものだと思う、それはそれが何であれ、それがネストされたクラスであるとは気付かなかった。 T :: iterator itr(container.begin())も同様です。タイプを構築する場合は、それ以外にどのように解釈することができますか?トピックについての私の無知のためにうそをついてください。 – rubixibuc

+0

@ rubixibuc-(私はこのメッセージを受け取る前に私の回答を少し更新しましたので、私の編集の最後を読んでみたいです)。私はあなたが "タイプを構築する"という意味を得ているのかどうかはわかりません。あなたは明確にすることができますか? – templatetypedef

0

は、既に述べたように、T::xを意味することができるTのメンバ関数xへのポインタを「T内で定義されるxタイプ(おそらくclass又はtypedefを)。それはまた、意味するかもしれません」。

コンパイラは、特定のキューに基づいて正しいものを特定することがよくあります(T::x fooまたはvoid (T::*)() foo = T::xと書いてありますか?)。 Visual StudioはGCCを使用していました(当時、人々はGCC上でコンパイルするためにコードを手に入れたが、Visual Studio上ではコンパイルしないために停止していた)。標準では、ハードケースを明確にするためにtypenameが必要です。

関連する問題