コンパイラーは、リストされたいくつかの型構造体で構成される型から、
テンプレート引き数を推定できます。
次の例は、いくつかの型構造体で構成される型からのテンプレート引き数の推定を示しています。
template<class T> class Y { }; template<class T, int i> class X { public: Y<T> f(char[20][i]) { return x; }; Y<T> x; }; template<template<class> class T, class U, class V, class W, int i> void g( T<U> (V::*)(W[20][i]) ) { }; int main() { Y<int> (X<int, 20>::*p)(char[20][20]) = &X<int, 20>::f; g(p); }
型 Y<int> (X<int, 20>::*p)(char[20][20]) T<U> (V::*)(W[20][i]) は、 型構造体 T (U::*)(V) に基づいています。
型が属するクラスを使用してその型を修飾し、そのクラス (ネストされた名前指定子) がテンプレート・パラメーターに依存する場合、コンパイラーは、そのパラメーターのテンプレート引き数を推定できません。 型が、この理由により推定できないテンプレート引き数を含んでいる場合、 その型にあるすべてのテンプレート引き数は、推定されません。 次の例は、このことを示しています。
template<class T, class U, class V> void h(typename Y<T>::template Z<U>, Y<T>, Y<V>) { }; int main() { Y<int>::Z<char> a; Y<int> b; Y<float> c; h<int, char, float>(a, b, c); h<int, char>(a, b, c); // h<int>(a, b, c); }
コンパイラーは、typename Y<T>::template Z<U> のテンプレート引き数 T および U を推定できません (しかし、Y<T> の T は推定します)。 コンパイラーは、U がそのコンパイラーによって推定されないので、 テンプレート関数呼び出し h<int>(a, b, c) を許可しません。
コンパイラーは、関数を指すポインターから、またはいくつかの多重定義関数名を与えられたメンバー関数引き数 を指すポインターから、関数テンプレート引き数を推定できます。 しかし、多重定義関数が、どれも関数テンプレートではないこともあれば、1 つ以上の多重定義関数が、要求される型と一致しないこともあります。 次の例は、このことを示しています。
template<class T> void f(void(*) (T,int)) { }; template<class T> void g1(T, int) { }; void g2(int, int) { }; void g2(char, int) { }; void g3(int, int, int) { }; void g3(float, int) { }; int main() { // f(&g1); // f(&g2); f(&g3); }
コンパイラーは、g1() が関数テンプレートなので、 呼び出し f(&g1) を許可しません。 コンパイラーは、g2() という名前の関数が、 両方とも f() が必要とする型と一致するので、呼び出し f(&g2) を許可しません。
コンパイラーは、デフォルト引き数の型からテンプレート引き数を推定できません。 次の例は、このことを示しています。
template<class T> void f(T = 2, T = 3) { }; int main() { f(6); // f(); f<int>(); }
コンパイラーは、関数呼び出しの引き数値からテンプレート引き数 (int) を推定できるので、 呼び出し f(6) を許可します。 コンパイラーは、f() のデフォルトの引き数からテンプレート引き数を推定できないので、 呼び出し f() を許可しません。
コンパイラーは、「非型」テンプレート引き数の型からテンプレート型引き数を推定できません。 例えば、コンパイラーは、次の表記を許可しません。
template<class T, T i> void f(int[20][i]) { }; int main() { int a[20][30]; f(a); }
コンパイラーは、テンプレート・パラメーター T の型を推定できません。
関連参照