このtemplateの意味がわかりません

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
dom

このtemplateの意味がわかりません

#1

投稿記事 by dom » 7年前

下記のコメント部分のtemplateはつけなくてもコンパイルできました。むしろこのような使用方法はエラーになるとも思いました。
これは構文的にどういう使用法で、どのような意味があるのでしょうか?

コード:

struct choose_range_list{
  template <typename T, std::size_t NumRanges>
  struct bind {
    typedef boost::array<T,1> type;
  };
};

template <typename T, std::size_t NumRanges>
struct range_list_generator {
private:
  typedef choose_range_list::choice Choice;
public:
  typedef typename Choice::template bind<T,NumRanges>::type type;
 //                        ↑これです
};

dom

Re: このtemplateの意味がわかりません

#2

投稿記事 by dom » 7年前

すみません。コードを少し訂正します。

コード:

struct choose_range_list{
  template <typename T, std::size_t NumRanges>
  struct bind {
    typedef boost::array<T,NumRanges> type;
  };
};
 
template <typename T, std::size_t NumRanges>
struct range_list_generator {
public:
  typedef typename choose_range_list::template bind<T,NumRanges>::type type;
 //                                     ↑これです
};

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: このtemplateの意味がわかりません

#3

投稿記事 by h2so5 » 7年前

template限定子という使い方があるみたいです。
http://d.hatena.ne.jp/faith_and_brave/2 ... 1201510970

コンパイラによっては必要らしいですが、僕もよく分かりません。
普通はつけなくても型推論できそうですけどね。

hoge

Re: このtemplateの意味がわかりません

#4

投稿記事 by hoge » 7年前

今回の例では多分いらない
templateの有無で意味が変わってしまう簡単な例を書いてみました

コード:

struct A {
    static const int foo = 0;
};
struct B {
    template <int N>
    struct foo{
        static const int bar = N;
    };
};
const int bar = 1;

template <class T>
struct C{
   static const int baz =  T::template foo<10>::bar;
};
int main()
{
  cout << C<B>::baz << endl;
//  cout << C<A>::baz << endl; // template を付けないとき有効
  return 0;
}


dom

Re: このtemplateの意味がわかりません

#5

投稿記事 by dom » 7年前

ご回答ありがとうございます。
なるほど、template限定子なるものがあるのですね。
具体例を示していただきありがとうございました。参考になりました。

アバター
tk-xleader
記事: 153
登録日時: 9年前
連絡を取る:

Re: このtemplateの意味がわかりません

#6

投稿記事 by tk-xleader » 7年前

 これは「Two Phase Name Look up」というテンプレートに関する名前探索によるものですね。規格上、コンパイラはテンプレートは定義時点と、インスタンス化される時点の2回に分けてテンプレートを解釈します。(VCはおそらくこれを無視してすべて(2)の時点で名前解決をしているから限定子がなくても通ってしまうのでしょう。しかしこれは規格違反です。)
(1)テンプレート定義時点
 テンプレート定義時点では、テンプレート引数に依存しない部分について解釈します。具体的には、; の漏れや、キーワードのスペルミスとかですね。また、テンプレート引数に依存しない名前について、その場で解決してしまいます。(※テンプレート自身と、テンプレート引数についてはこの時点で解決される。)
(2)インスタンス化される時点
 インスタンス化される時点では、(1)で解決できなかった部分。つまりテンプレート引数に依存する部分について解釈します。よって、テンプレート引数に依存する名前については、この時点で解決されることになります。

 では、どのようなときにtypename限定子やtemplate限定子が必要になるのかというと、基本的には、その文脈においてテンプレートパラメータに依存している型名やメンバテンプレートが出てきたときです。たとえば、

コード:

//(A)
template<typename T,int V>
struct X{
	void func(){
		T::u<V> val; //(T::u < V) > val; と解釈される
	}
}

コード:

//(B)
template<typename T,int V>
struct X{
	void func(){
		T::template u<V> val; //今度はT::uをテンプレートとして解釈する。
	}
}
 domさんが提示したコードではtemplate限定子が必要ないのは、choose_range_list::bind自体はrange_list_generatorのテンプレートパラメータに依存した名前じゃないからです。(ただし、choose_range_list::bind<T,NumRanges>::type はテンプレートパラメータに思いっきり依存しているのでtypenameが必要ですけどね。)

コード:

struct choose_range_list{
  template <typename T, std::size_t NumRanges>
  struct bind {
    typedef boost::array<T,NumRanges> type;
  };
};
 
template <typename T, std::size_t NumRanges>
struct range_list_generator {
public:
  typedef typename choose_range_list::template bind<T,NumRanges>::type type;
 //                                     ↑これです
};

閉鎖

“C言語何でも質問掲示板” へ戻る