Template Advancement
Untyped parameter template
Template parameter classification type shape participates in untyped parameter classification.
Type parameters are: they appear in the template parameter list, followed by parameter type names such as class or typename.
Untyped parameter is a parameter of class (function) template, which can be used as a constant in class (function) template.
// Define a static array of template types template<class T, size_t N = 10> class Array { public: T& operator[](size_t index) { return _array[index]; } const T& operator[](size_t index)const { return _array[index]; } size_t Size()const { return _size; } bool Empty()const { return 0 == _size; } private: T _array[N]; size_t _size; };
- Floating-point numbers, class objects, and strings are not allowed as untyped template parameters.
- Untyped template parameters must be validated at compile time.
Template specialization
concept
Typically, you can use templates to implement type-independent code, but for some special types you may get some wrong results
For example:
template<class T> bool IsEqual(T& left, T& right) { return left == right; } void Test() { char* p1 = "world"; char* p2 = "hello"; if(IsEqual(p1, p2)) cout<<p1<<endl; else cout<<p2<<endl; // Output hello // Because it's the address that's coming in. // Comparing address size with string size }
Function template specialization
Specification steps for function templates:
- There must be a basic function template first.
- Keyword template followed by a pair of empty brackets <>
- Function names are followed by a pair of parentheses, in which the type to be specialized is specified
- Functional parametric table: Must be exactly the same as the basic parameter type of template function, if different compilers may report some strange errors.
template<> bool IsEqual<char*>(char*& left, char*& right) { if(strcmp(left, right) > 0) return true; return false; } // Normally, if a function template encounters a type that cannot be handled or that has been handled incorrectly, // In order to achieve simplicity, this function is usually given directly. bool IsEqual(char* left, char* right) { if(strcmp(left, right) > 0) return true; return false; }
Full Specialization
Full specialization means that all the parameters in the template parameter class table are determined.
template<class T1, class T2> class Data { public: Data() {cout<<"Data<T1, T2>" <<endl;} private: T1 _d1; T2 _d2; }; template<> class Data<int, char> { public: Data() {cout<<"Data<int, char>" <<endl;} private: int _d1; char _d2; }; void TestVector() { Data<int, int> d1; Data<int, char> d2; }
partial specialization
Partialization: Any special version that further restricts the design of template parameters. For example, for the following template classes:
template<class T1, class T2> class Data { public: Data() {cout<<"Data<T1, T2>" <<endl;} private: T1 _d1; T2 _d2; };
There are two manifestations of partial specialization
partial specialization
Specialization of some of the parameters in the template parameter class table
// Specialize the second parameter to int template <class T1> class Data<T1, int> { public: Data() {cout<<"Data<T1, int>" <<endl;} private: T1 _d1; int _d2; };
Further constraints on parameters
Partialization is not only a partial parameter specialization, but a special version designed for further jump limitation of template parameters.
//Partialization of two parameters to pointer type template <typename T1, typename T2> class Data <T1*, T2*> { public: Data() {cout<<"Data<T1*, T2*>" <<endl;} private: T1 _d1; T2 _d2; }; template <typename T1, typename T2> class Data <T1&, T2&> { public: Data(const T1& d1, const T2& d2) : _d1(d1) , _d2(d2) { cout<<"Data<T1&, T2&>" <<endl; } private: const T1 & _d1; const T2 & _d2; }; void test2 () { Data<double , int> d1; // Invoke the specialized int version Data<int , double> d2; // Call the underlying template Data<int *, int*> d3; // Call Specialized Pointer Version Data<int&, int&> d4(1, 2); // Call Specialized Pointer Version }