テンプレート関数を呼び出す場合、
テンプレート関数呼び出しの使い方とそのコンテキストによって、
コンパイラーが決定または推定 できるテンプレート引き数は、どれでも省略できます。
コンパイラーは、対応するテンプレート・パラメーターの型と、 関数呼び出しで使用される引き数の型を比較することにより、 テンプレート引き数を推定しようとします。 テンプレート引き数の推定を行うためには、コンパイラーが比較する 2 つの型 (テンプレート・パラメーターと関数呼び出しで使用される引き数) は、 ある特定の構造体でなければなりません。 下記に、これらの型構造体をリストします。
T const T volatile T T& T* T[10] A<T> C(*)(T) T(*)() T(*)(U) T C::* C T::* T U::* T (C::*)() C (T::*)() D (C::*)(T) C (T::*)(U) T (C::*)(U) T (U::*)() T (U::*)(V) E[10][i] B<i> TT<T> TT<i> TT<C>
次の例は、これら型構造体のそれぞれの使用法を示しています。 例では、引き数として上記の各構造体を使用して、テンプレート関数を宣言しています。 そして、これらの関数が、宣言の順序で (テンプレート引き数を使用せずに) 呼び出されます。 この例は、型構造体のリストと同様なものを出力します。
#include <iostream> using namespace std; template<class T> class A { }; template<int i> class B { }; class C { public: int x; }; class D { public: C y; int z; }; template<class T> void f (T) { cout << "T" << endl; }; template<class T> void f1(const T) { cout << "const T" << endl; }; template<class T> void f2(volatile T) { cout << "volatile T" << endl; }; template<class T> void g (T*) { cout << "T*" << endl; }; template<class T> void g (T&) { cout << "T&" << endl; }; template<class T> void g1(T[10]) { cout << "T[10]" << endl;}; template<class T> void h1(A<T>) { cout << "A<T>" << endl; }; void test_1() { A<char> a; C c; f(c); f1(c); f2(c); g(c); g(&c); g1(&c); h1(a); } template<class T> void j(C(*)(T)) { cout << "C(*) (T)" << endl; }; template<class T> void j(T(*)()) { cout << "T(*) ()" << endl; } template<class T, class U> void j(T(*)(U)) { cout << "T(*) (U)" << endl; }; void test_2() { C (*c_pfunct1)(int); C (*c_pfunct2)(void); int (*c_pfunct3)(int); j(c_pfunct1); j(c_pfunct2); j(c_pfunct3); } template<class T> void k(T C::*) { cout << "T C::*" << endl; }; template<class T> void k(C T::*) { cout << "C T::*" << endl; }; template<class T, class U> void k(T U::*) { cout << "T U::*" << endl; }; void test_3() { k(&C::x); k(&D::y); k(&D::z); } template<class T> void m(T (C::*)() ) { cout << "T (C::*)()" << endl; }; template<class T> void m(C (T::*)() ) { cout << "C (T::*)()" << endl; }; template<class T> void m(D (C::*)(T)) { cout << "D (C::*)(T)" << endl; }; template<class T, class U> void m(C (T::*)(U)) { cout << "C (T::*)(U)" << endl; }; template<class T, class U> void m(T (C::*)(U)) { cout << "T (C::*)(U)" << endl; }; template<class T, class U> void m(T (U::*)() ) { cout << "T (U::*)()" << endl; }; template<class T, class U, class V> void m(T (U::*)(V)) { cout << "T (U::*)(V)" << endl; }; void test_4() { int (C::*f_membp1)(void); C (D::*f_membp2)(void); D (C::*f_membp3)(int); m(f_membp1); m(f_membp2); m(f_membp3); C (D::*f_membp4)(int); int (C::*f_membp5)(int); int (D::*f_membp6)(void); m(f_membp4); m(f_membp5); m(f_membp6); int (D::*f_membp7)(int); m(f_membp7); } template<int i> void n(C[10][i]) { cout << "E[10][i]" << endl; }; template<int i> void n(B<i>) { cout << "B<i>" << endl; }; void test_5() { C array[10][20]; n(array); B<20> b; n(b); } template<template<class> class TT, class T> void p1(TT<T>) { cout << "TT<T>" << endl; }; template<template<int> class TT, int i> void p2(TT<i>) { cout << "TT<i>" << endl; }; template<template<class> class TT> void p3(TT<C>) { cout << "TT<C>" << endl; }; void test_6() { A<char> a; B<20> b; A<C> c; p1(a); p2(b); p3(c); } int main() { test_1(); test_2(); test_3(); test_4(); test_5(); test_6(); }
関連参照