templateのテンプレートにおけるclassとtypenameの違い


前言traitsのプログラミングを分析する前に、テンプレートパラメータのタイプtempnameclassに対して一定の理解が必要で、彼らがどのような面で異なるのか、どのような面で同じなのかを理解してこそ、traitsのプログラミングの核心を体得することができる.もしあなたが両者を理解したら、次の編を直接見ることができます.
同じところ
テンプレートパラメータの種類typenameclassは、一般に同じであると考える.この両者はパラメータタイプにおいて確かに同じである.あなたは書くことができます
template<class T> 
class point {};

書くこともできます
template<typename T>
class point {};

どちらも同じで、違いはありません.両者typenameclassはパラメータタイプにおいて異なるものではない
同じである以上、なぜこの2つの記号を定義しますか?
  • テンプレートを定義する最初の方法はtemplateですが、classはあくまでクラスと考えられており、使用時に少し混同されるのは避けられません.つまりtypenameを定義してパラメータタイプ
  • をマークします.
  • の最も重要なtypenameについては、ネスト依存型、すなわちタイプがネスト可能である.これも二つの違いです.

  • 相違点typenameはネスト依存に用いることができ、そのタイプを表すが、classにはそのような機能はない.
    ネスト依存とは?簡単な例で見ると
    template<class T>
    class people
    {
    	public:
    		typedef T	value_type;
    		typedef T*	pointer;
    		typedef T&	reference;
    };
    
    template<class T>
    struct man 
    {
    	public:
    		typedef typename T::value_type	value_type;
    		typedef typename T::pointer		pointer;
    		typedef typename T::reference	reference;
    		void print()
    		{
    			cout << "man" << endl;
    		}
    };
    
    int main()
    {
    	man<people<int>> Man;
    	Man.print();
    
    	exit(0);
    }
    

    以上がtypenameのネスト使用である.typenameは、コンパイラにこれは関数ではなく、変数ではなくタイプであることを示す.ここでtypedefを用いてパラメータタイプを再定義する.間接性が増す2.使うときも長いコードを書く必要はありません.
    ここでtypenameは、peopleクラスで定義タイプを一度抽出したものであり、ここでtypenameclassに変更するとエラーとなる.typename主な役割:
  • テンプレートパラメータがクラスである場合、typenameはそのクラスで定義パラメータタイプを抽出することができる.

  • すべてのネスト依存タイプにtypenameを付けるわけではありません.例外として、継承リストまたはメンバー初期化リストでベースクラスを初期化する場合、typenameキーワードを削除できます.
    man(int x) : T::value_type(x) {}
    

    まとめ
    ここではtypenameについて簡単な分析を行い、traitsのプログラミングの基礎を分析するのに十分である.以上の分析をもう一つまとめます.
  • typenameclassは、パラメータタイプとして用いる場合と同様に、
  • と区別されない.
  • typenameは、主にネスト依存型の抽出(抽出)に用いる.classにはこのような機能はない.
  • typename抽出の1つの例外は、継承またはメンバー初期化リストにおいてベースクラスを初期化する際にtypenameキーワード
  • を追加する必要がないことである.