ページ 1 / 1
このtemplateの意味がわかりません
Posted: 2013年3月26日(火) 22:35
by dom
下記のコメント部分の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;
// ↑これです
};
Re: このtemplateの意味がわかりません
Posted: 2013年3月26日(火) 22:39
by dom
すみません。コードを少し訂正します。
コード:
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;
// ↑これです
};
Re: このtemplateの意味がわかりません
Posted: 2013年3月26日(火) 22:52
by h2so5
template限定子という使い方があるみたいです。
http://d.hatena.ne.jp/faith_and_brave/2 ... 1201510970
コンパイラによっては必要らしいですが、僕もよく分かりません。
普通はつけなくても型推論できそうですけどね。
Re: このtemplateの意味がわかりません
Posted: 2013年3月27日(水) 03:15
by hoge
今回の例では多分いらない
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;
}
Re: このtemplateの意味がわかりません
Posted: 2013年3月27日(水) 11:11
by dom
ご回答ありがとうございます。
なるほど、template限定子なるものがあるのですね。
具体例を示していただきありがとうございました。参考になりました。
Re: このtemplateの意味がわかりません
Posted: 2013年3月27日(水) 16:41
by tk-xleader
これは「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;
// ↑これです
};