c++ template学习总结【转】
- #include <stdexcept>
- template <typename T, int MAXSIZE>
- class Stack {
- private:
- T elems[MAXSIZE]; // elements
- int numElems; // current number of elements
- public:
- Stack(); // constructor
- void push(T const&); // push element
- void pop(); // pop element
- T top() const; // return top element
- bool empty() const { // return whether the stack is empty
- return numElems == 0;
- }
- bool full() const { // return whether the stack is full
- return numElems == MAXSIZE;
- }
- };
- // constructor
- template <typename T, int MAXSIZE>
- Stack<T,MAXSIZE>::Stack ()
- : numElems(0) // start with no elements
- {
- // nothing else to do
- }
- template <typename T, int MAXSIZE>
- void Stack<T,MAXSIZE>::push (T const& elem)
- {
- if (numElems == MAXSIZE) {
- throw std::out_of_range("Stack<>::push(): stack is full");
- }
- elems[numElems] = elem; // append element
- ++numElems; // increment number of elements
- }
- template<typename T, int MAXSIZE>
- void Stack<T,MAXSIZE>::pop ()
- {
- if (numElems <= 0) {
- throw std::out_of_range("Stack<>::pop(): empty stack");
- }
- --numElems; // decrement number of elements
- }
- template <typename T, int MAXSIZE>
- T Stack<T,MAXSIZE>::top () const
- {
- if (numElems <= 0) {
- throw std::out_of_range("Stack<>::top(): empty stack");
- }
- return elems[numElems-1]; // return last element
- }
#include <stdexcept> template <typename T, int MAXSIZE> class Stack { private: T elems[MAXSIZE]; // elements int numElems; // current number of elements public: Stack(); // constructor void push(T const&); // push element void pop(); // pop element T top() const; // return top element bool empty() const { // return whether the stack is empty return numElems == 0; } bool full() const { // return whether the stack is full return numElems == MAXSIZE; } }; // constructor template <typename T, int MAXSIZE> Stack<T,MAXSIZE>::Stack () : numElems(0) // start with no elements { // nothing else to do } template <typename T, int MAXSIZE> void Stack<T,MAXSIZE>::push (T const& elem) { if (numElems == MAXSIZE) { throw std::out_of_range("Stack<>::push(): stack is full"); } elems[numElems] = elem; // append element ++numElems; // increment number of elements } template<typename T, int MAXSIZE> void Stack<T,MAXSIZE>::pop () { if (numElems <= 0) { throw std::out_of_range("Stack<>::pop(): empty stack"); } --numElems; // decrement number of elements } template <typename T, int MAXSIZE> T Stack<T,MAXSIZE>::top () const { if (numElems <= 0) { throw std::out_of_range("Stack<>::top(): empty stack"); } return elems[numElems-1]; // return last element }
接下来编写我们的测试函数:
- #include <iostream>
- #include <string>
- #include <cstdlib>
- #include "stack4.hpp"
- int main()
- {
- try {
- Stack<int,20> int20Stack; // stack of up to 20 ints
- Stack<int,40> int40Stack; // stack of up to 40 ints
- Stack<std::string,40> stringStack; // stack of up to 40 strings
- // manipulate stack of up to 20 ints
- int20Stack.push(7);
- std::cout << int20Stack.top() << std::endl;
- int20Stack.pop();
- // manipulate stack of up to 40 strings
- stringStack.push("hello");
- std::cout << stringStack.top() << std::endl;
- stringStack.pop();
- stringStack.pop();
- }
- catch (std::exception const& ex) {
- std::cerr << "Exception: " << ex.what() << std::endl;
- return EXIT_FAILURE; // exit program with ERROR status
- }
- }
#include <iostream> #include <string> #include <cstdlib> #include "stack4.hpp" int main() { try { Stack<int,20> int20Stack; // stack of up to 20 ints Stack<int,40> int40Stack; // stack of up to 40 ints Stack<std::string,40> stringStack; // stack of up to 40 strings // manipulate stack of up to 20 ints int20Stack.push(7); std::cout << int20Stack.top() << std::endl; int20Stack.pop(); // manipulate stack of up to 40 strings stringStack.push("hello"); std::cout << stringStack.top() << std::endl; stringStack.pop(); stringStack.pop(); } catch (std::exception const& ex) { std::cerr << "Exception: " << ex.what() << std::endl; return EXIT_FAILURE; // exit program with ERROR status } }
大家要注意int20Stack和int40Stack是两个不同的类型,他们是不能进行硬是或者显示的转换的。也不能够相互赋值。
你还可以为函数模板定义非型别参数:
- template <typename T, int VAL>
- T addValue (T const& x)
- {
- return x + VAL;
- }
template <typename T, int VAL> T addValue (T const& x) { return x + VAL; }
当我们想把【函数】和某种操作作为参数传递的时候,就非常有用,比如在使用STL时,你可能有下面的代码:
- std::transform (source.begin(), source.end(), // start and end of source
- dest.begin(), // start of destination
- addValue<int,5>); // operation
std::transform (source.begin(), source.end(), // start and end of source dest.begin(), // start of destination addValue<int,5>); // operation
有时候我们为了使得编译器推导的时候简单一些,可以使用:
- std::transform (source.begin(), source.end(), // start and end of source
- dest.begin(), // start of destination
- (int(*)(int const&)) addValue<int,5>); // operation
std::transform (source.begin(), source.end(), // start and end of source dest.begin(), // start of destination (int(*)(int const&)) addValue<int,5>); // operation
但是我们要注意,非类型模板参数也有自己的局限,通常来说他们只能是常整数,包括枚举,或者指向外部链接的指针。如果我们用浮点数或者class-type objects作为非类型模板参数是错误的:
- template <double VAT> // ERROR: floating-point values are not
- double process (double v) // allowed as template parameters
- {
- return v * VAT;
- }
- template <std::string name> // ERROR: class-type objects are not
- class MyClass { // allowed as template parameters
- …
- };
template <double VAT> // ERROR: floating-point values are not double process (double v) // allowed as template parameters { return v * VAT; } template <std::string name> // ERROR: class-type objects are not class MyClass { // allowed as template parameters … };
由于字串字面常熟是一种采用内部链接的物件,也就是说不通模组中的两个同值的字串字面常数其实是两个不同的东西,所以他们也不能用来作为模板参数:
- template <char const* name>
- class MyClass {
- …
- };
- MyClass<"hello"> x; // ERROR: string literal "hello" not allowed
template <char const* name> class MyClass { … }; MyClass<"hello"> x; // ERROR: string literal "hello" not allowed
此外全局指针也是不行的:
- template <char const* name>
- class MyClass {
- …
- };
- char const* s = "hello";
- MyClass<s> x; // ERROR: s is pointer to object with internal linkage
template <char const* name> class MyClass { … }; char const* s = "hello"; MyClass<s> x; // ERROR: s is pointer to object with internal linkage
但是下面的例子是可以的:
- template <char const* name>
- class MyClass {
- …
- };
- extern char const s[] = "hello";
- MyClass<s> x; // OK
template <char const* name> class MyClass { … }; extern char const s[] = "hello"; MyClass<s> x; // OK
在这个例子中,s是一个外部连接的部件。
============================================================================== 我喜欢程序员,他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其实我是一个程序员。