"C++Templates The Complete Guide"讀書筆記----Chapter 5
1. To access a type name that depends on a template parameter, you have to?qualify(?修改,修飾) the name with a leading typename
//?print?elements?of?an?STL?container
template?<typename?T>
void?printcoll?(T?const&?coll)

{
????typename?T::const_iterator?pos;??//?iterator?to?iterate?over?coll
????typename?T::const_iterator?end(coll.end());??//?end?position

????for?(pos=coll.begin();?pos!=end;?++pos)?
{
????????std::cout?<<?*pos?<<?'?';
????}
????std::cout?<<?std::endl;
}2. Nested classes and member functions can also be templates. One application is the ability to implement generic operations with internal type conversions. However, type checking still occurs.

class?Stack?
{
??private:
????std::deque<T>?elems;???//?elements
??public:
????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?elems.empty();
????}
????//?assign?stack?of?elements?of?type?T2
????template?<typename?T2>
????Stack<T>&?operator=?(Stack<T2>?const&);
};
template?<typename?T>
?template?<typename?T2>
Stack<T>&?Stack<T>::operator=?(Stack<T2>?const&?op2)

{
????if?((void*)this?==?(void*)&op2)?
{????//?assignment?to?itself?
????????return?*this;
????}
????Stack<T2>?tmp(op2);??????????????//?create?a?copy?of?the?assigned?stack
????elems.clear();???????????????????//?remove?existing?elements
????while?(!tmp.empty())?
{???????????//?copy?all?elements
????????elems.push_front(tmp.top());
????????tmp.pop();
????}
????return?*this;
}
3. Template versions of assignment operators don't replace default assignment operators
4. You can also use class templates as template parameters, as so-called template template parameters
To use a different internal container for stacks, the application programmer has to specify the element type twice. Thus, to specify the type of the internal container, you have to pass the type of the container and the type of its elements again:
Stack<int,std::vector<int>?>?vStack;?//?integer?stack?that?uses?a?vector
Using template template parameters allows you to declare the Stack class template by spcecifying the type of the container without respecifying the type of its elements:stack<int,?std::vector>?vStack;?//?integer?stack?the?uses?a?vector
To do this you must specify the second template parameter as a template template parameter.
template?<typename?T,
??????????template?<typename?ELEM>?class?CONT?=?std::deque?>
class?Stack?
{
??private:
????CONT<T>?elems;?????????//?elements
??public:
????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?elems.empty();
????}
};template?<typename?ELEM>?class?CONT
5. Template template arguments must match exactly. Default template arguments of template template arguments are ignored
The problem in this example is that the std::deque template of the standard library has more than one parameter: the second parameter has a default value, but this is not considered when match std::deque to the CONT parameter.
We can rewrite te class declaration so that the CONT parameter expects containers with two template parameters:
template?<typename?T,
??????????template?<typename?ELEM,?
????????????????????typename?ALLOC=?std::allocator<ELEM>?>
????????????????????class?CONT?=?std::deque>
class?Stack?
{
??private:
????CONT<T>?elems;?????????//?elements

};
7.? For string literals there is an array-to-pointer conversion during argument deduction if and only if the parameter is not a reference
Passing string literal arguments for reference parameters of templates sometimes fails in a surprising way.
//?note:?reference?parameters
template?<typename?T>
inline?T?const&?max?(T?const&?a,?T?const&?b)

{
????return??a?<?b?????b?:?a;
}
int?main()

{
????std::string?s;
????::max("apple","peach");???//?OK:?same?type
????::max("apple","tomato");??//?ERROR:?different?types
????::max("apple",s);?????????//?ERROR:?different?types
}However, if you declare nonreference parameters, you can substitute them with string literals of different size:
//?note:?nonreference?parameters
template?<typename?T>
inline?T?max?(T?a,?T?b)

{
????return??a?<?b?????b?:?a;
}
int?main()

{
????std::string?s;
????::max("apple","peach");???//?OK:?same?type
????::max("apple","tomato");??//?OK:?decays?to?same?type
????::max("apple",s);?????????//?ERROR:?different?types
}
template?<typename?T>
void?ref?(T?const&?x)

{
????std::cout?<<?"x?in?ref(T?const&):?"??
??????????????<<?typeid(x).name()?<<?'\n';
}
template?<typename?T>
void?nonref?(T?x)

{
????std::cout?<<?"x?in?nonref(T):?????"
??????????????<<?typeid(x).name()?<<?'\n';
}
int?main()

{
????ref("hello");
????nonref("hello");
}the output might be as follows:
x in ref(T const&): char[6]
x in nonref(T): const char *
posted on 2006-12-01 15:41 ningfangli 閱讀(167) 評論(0) 編輯 收藏 引用
