15

次のプログラムを作りました

#include <iostream>
#include <typeinfo>
template<class T>
struct Class
{
    template<class U>
    void display(){

        std::cout<<typeid(U).name()<<std::endl;
        return ;
    }

};


template<class T,class U>
void func(Class<T>k)
{
    k.display<U>(); 

}

int main()
{
    Class<int> d;
    func<int,double>(d);
}

上記のプログラムdisplay()はテンプレートメンバー関数であるためコンパイルされないため、.templatebeforeの修飾を行うdisplay()必要があります。私は正しいですか?

しかし、私が次のプログラムを作ったとき

#include <iostream>
#include <typeinfo>

template<typename T>
class myClass
{
    T dummy;
    /*******/
public:
    template<typename U>
    void func(myClass<U> obj);

};

template<typename T>
template<typename U>

void myClass<T>::func(myClass<U> obj)
{
    std::cout<<typeid(obj).name()<<std::endl;
}
template<class T,class U>
void func2(myClass<T>k)
{
    k.template func<U>(k); //even it does not compile

}
int main()
{
    myClass<char> d;
    func2<char,int>(d);
    std::cin.get();
}

コンストラクトk.func<char>(k);を与えてもコンパイルされないのはなぜですか?.template

4

4 に答える 4

36

<記号は、「より小さい」と「テンプレート引数の開始」の両方を意味します。これらの2つの意味を区別するために、パーサーは、先行するIDがテンプレートに名前を付けているかどうかを知る必要があります。

たとえば、コードを考えてみましょう

template< class T >
void f( T &x ) {
    x->variable < T::constant < 3 >;
}

またははテンプレートである必要がありますT::variableT::constant関数は、どちらがそうでないかによって異なることを意味します。

  1. どちらかT::constantが3と比較され、ブール結果が次のテンプレート引数になります。T::variable<>
  2. またT::constant<3>はと比較されx->variableます。

曖昧さを解消するには、またはのtemplate前にキーワードが必要です。ケース1:variableconstant

template< class T >
void f( T &x ) {
    x->template variable < T::constant < 3 >;
}

ケース2:

template< class T >
void f( T &x ) {
    x->variable < T::template constant < 3 >;
}

キーワードが実際のあいまいな状況(まれな状況)でのみ必要とされるといいのですが、パーサーを作成するのがはるかに簡単になり、そのような問題があなたを驚かせるのを防ぎます。

標準については、14.2/4を参照してください。

メンバーテンプレートの特殊化の名前が。の後に表示される場合。または->postfix-expressionの場合、または修飾IDのnested-name-specifierの後に、postfix-expressionまたはqualified-idが明示的にtemplate-parameter(14.6.2)に依存する場合、メンバーのテンプレート名は次のようになります。キーワードテンプレートのプレフィックス。それ以外の場合、その名前は非テンプレートの名前であると見なされます。

于 2010-08-17T23:56:28.827 に答える
7

C ++テンプレートのセクション5.1では、この構成について詳しく説明しています。

以下の関数に問題があります

template<class T,class U> 
void func2(myClass<T> k) 
{ 
    k.template func<U>(k); //even it does not compile 

} 

ここで、T=charおよびU=int

myclass<char>::func<int>(myclass<char>) 

と呼ばれています。ただし、そのような機能は存在しません

通常の状況では、「char」は「int」に変換可能ですが、これは明示的に指定されたテンプレート引数には適していません。

于 2010-08-17T05:08:14.333 に答える
0

この標準では、テンプレートコンテキストに依存するものを明確templateにするために、またはtypenameキーワードが必要です。

于 2010-08-17T03:36:13.693 に答える
0

最初の例は、VS2010でコンパイルして正常に実行されます。

于 2010-08-17T03:38:52.553 に答える