Basic Template Terminology
1. "Class Template" or "Template Class"?
class template: the class is a template.
template class: a synonym(同义词) for class template; to refer to classes generated from templates(由模板产生(实例化)的类). to refer to classes with a name that is a template-id.
Because of this imprecision, template class is avoided in this book.
2. Instantiation and specialzation
Instantiation: 实例化. The process of creating a regular class, function, or member function from a template by substituting actual values for its arguments is called template instantiation.
Specialzation:特例,在Chapter 3中有描述
3. Declarations vs Definitions
declaration is a C++ construct that introduces or reintroduceds a name into a C++ scope.
class C; // a declaration of C as a class
void f(int p); // a declaration of f() as a function and p as a named parameter
extern int v; // a declaration of v as a variable
Declarations become definitions when the details of their structure are made known or, in the case of variables, when storage space must be allocated.
class C{}; // definition(and declaration) of class C
void f(int p){ // defini
std::cout<< p << std::endl;
}
extern int v = 1; // an initializer makes this a definition for v
int w; // global variable declaration not preceded by extern are also definitions By extension, the declaration of a class template or function template is called a definition if it has a body, Hence,
template <typename T>
void func(T);
is a declaration that is not a definition, whereas
template <typename T>
class S{};
is in fact a definition
Using Templates in Practice
1. Templates challenge the classic compiler-plus-linker model. Therefore there are different approaches to organize template code: the inclusion model, explicit instantiation, and the separation model
Most C and C++ programmers organize their nontemplate code largely as follows:
1) Classes and other types are entirely placed in header files.
2) For global variables and (noninline) functions, only a declaration is put in a header file, and the definition goes into a so-called dot-C file.
The works well: It makes the needed type definition easily available throughout the program and avoids duplicate definition errors on variables and functions from the linker.
With the convention in mind, we declare the template in a header file:
#ifndef MYFIRST_HPP
#define MYFIRST_HPP
// declaration of template
template <typename T>
void print_typeof (T const&);
#endif // MYFIRST_HPP The implementation of the function is placed in a dot-C file:
#include <iostream>
#include <typeinfo>
#include "myfirst.hpp"
// implementation/definition of template
template <typename T>
void print_typeof (T const& x)
{
std::cout << typeid(x).name() << std::endl;
} Finally, we use the template in another dot-C file, into which our template declaration is #include:
#include "myfirst.hpp"
// use of the template
int main()
{
double ice = 3.0;
print_typeof(ice); // call function template for type double
} A C++ compiler will most likely accept this program without any problems,but
the linker will probably report an error,
implying that there is no definition of the function print_typeof().
In order for a template to be instantiated, the compiler
must know which definition should be instantiated and for what template arguments it should be instantiated. Unfortunately, these
two pieces of information are in files that are compiled separatedly. Therefore, when our compiler sees the call to print_typeof() but has no definition in sight to instantiate this function for
double, it just assumes that such a definition is provided elsewhere and creates a reference(
for the linker to resolve,linker) to that definition. On the other hand, when the compiler processes the file myfirst.cpp, it has no indication at that point that it must instantiate the template definition it contains for specific arguments.
The Inclusion Model
Rewrite the header-file, including template definition.
#ifndef MYFIRST_HPP
#define MYFIRST_HPP
#include <iostream>
#include <typeinfo>
// declaration of template
template <typename T>
void print_typeof (T const&);
// implementation/definition of template
template <typename T>
void print_typeof (T const& x)
{
std::cout << typeid(x).name() << std::endl;
}
#endif // MYFIRST_HPP disadvantage: the cost is not the result of size of the template definition itself, but the result of the fact that we must also include the header used by the definition of our template-in the case <iostream> and <typeinfo>.\
Explicit Instantiation
To avoid above linker error we can add the following file to our program:
#include "myfirst.cpp"
// explicitly instantiate print_typeof() for type double
template void print_typeof<double>(double const&); disadvantage: We must carefully keep track of which entities to instantiate. For large projects this quickly becomes an excessive burden.
advantage:
the instantiation can be tuned to the needs of the program.
The overhead of large header is avoided.
The source code of template definition can be kept hidden, but then no additional instantiations can be created by a client program.
Finally, for some applications it can be useful to control the exact location(that is, the object file)of a template instance.
Separation model
2. Usually you should use the inclusion model
3. By separating template code into different header files for declarations and definitions, you can more easily switch between the inclusion model and explicit instantiation
4. The C++ standard defines a separate compilation model for templates(using the keyword export). It is not yet widely available, however.
5. To take advantage of precompiled headers, be sure to keep the same order for #include directives.
6. Debuggin code with templates can be challenging
7. Template instances may have very long names
杀毒就用卡巴:(不敢恭维,原来用过,很耗资源)
木马就用Ewido:(刚装上,破解比较麻烦,文件中有整个包,看到大家的评价不错,官方下载:
http://download.ewido.net/ewido-setup.exe;)
防火墙就用ZoneAlarm: (还是不用的好,这个好麻烦,总要你确认是否允许联网,就用xp的防火墙吧)
这三个合起来用,可以使得系统坚若磐石
它们每个都是当今世界最强的,不用是你的损失!!
卡巴和ZoneAlarm同时安装时,记得在卡巴的实时保护设置里,把那个禁止网络攻击保护打上钩!!!!!!不然会冲突!!! 切记!!!(如果只安装卡巴的话就不用这样做了)
今天晚上,已经是我两周以来第二次恢复笔记本的系统了,好在有true image啊!。原因都是一样:在上网找一些软件时,不幸中招。
我还一直很小心不断升级Symantec。将防火墙开启。也真不知道哪个防毒软件真的好使,也不知道怎么这么多人希望弄这些病毒!
无奈!
摘要: 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 containertemplate <typename T>void printcol...
阅读全文
Chapter 4 Nontype Template Parameters
1. Templates can have template parameters that are values rather than types
With this class, user of the stack could specify this size of the array as the maximum size needed for stack elements
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
} 2. You can also define nontype parameters for function templates.
template <typename T, int VAL>
T addValue (T const& x)
{
return x + VAL;
} However, according to the current standard, sets of overloaded functions cannot be used for template parameter deduction. Thus, you have to cast to the exact type of the function template argument:
std::transform(source.begin(),source.end(),// start and end of source
dest.begin(),// start of destination
(int(*)(int const&))addValue<int,5>);//operation
There is a proposal for the standard to fix this behavior so that the cast isn't necessary.
2. You cannot use floating-point numbers, class-type objects, and objects with internal linkage(such as string literals) as arguments for nontype template parameters
这段时间在通过"C++Templates The Complete Guide"这本书学习Templates。发现这本书确实不错:语言简明,内容翔实。特别是每章后面的Summery总结得很好。这份读书笔记就已这个Summery为基础写的。
书前面的Prefece和Chapter 1就跳过了。既然来学习Templates就已经知道它的重要性了。
Chapter 2 FunctionTemplates
1. Function templates define a family of functions for different template arguments;
template
<
typename T
>
inline T
const
&
max (T
const
&
a, T
const
&
b)
{
//
if a < b then use b else use a
return
a
<
b
?
b : a;
}
2. When you pass template arguments, function templates are instantiated for these argument types.
The process of replacing templates parameters by concrete types is called instantiatin.(at compiled time)
3. You can explicitly qualify the template parameters
{
//
because no automatic type conversion if allowed in templates,so
max(static_cast
<
double
>
(
4
),
4.2
)
//
cast the arguments so that they both match
max
<
double
>
(
4
,
4.2
)
//
specify explicitly the type of T
}
4. You can overload funciton templates
inline
int
const
&
max (
int
const
&
a,
int
const
&
b)
{
return
a
<
b
?
b : a;
}
//
maximum of two values of any type
template
<
typename T
>
inline T
const
&
max (T
const
&
a, T
const
&
b)
{
return
a
<
b
?
b : a;
}
//
maximum of three values of any type
template
<
typename T
>
inline T
const
&
max (T
const
&
a, T
const
&
b, T
const
&
c)
{
return
::max (::max(a,b), c);
}
int
main()
{
::max(
7
,
42
,
68
);
//
calls the template for three arguments
::max(
7.0
,
42.0
);
//
calls max<double> (by argument deduction)
::max(
'
a
'
,
'
b
'
);
//
calls max<char> (by argument deduction)
::max(
7
,
42
);
//
calls the nontemplate for two ints
::max
<>
(
7
,
42
);
//
calls max<int> (by argument deduction)
::max
<
double
>
(
7
,
42
);
//
calls max<double> (no argument deduction)
::max(
'
a
'
,
42.7
);
//
calls the nontemplate for two ints
}
ps: the overload resolution process normally prefers this nontemplate over one generated from the template. the fourth call falls under this rule.
5. When you overload function templates, limit your changes to specifying template parameters explicitly
{
max
<>
(
7
,
42
);
//
call max<int> (by argument deduction)
}
6. Make sure you see all overloaded versions of funciton templates before you call them
template
<
typename T
>
inline T
const
&
max (T
const
&
a, T
const
&
b)
{
return
a
<
b
?
b : a;
}
//
maximum of three values of any type
template
<
typename T
>
inline T
const
&
max (T
const
&
a, T
const
&
b, T
const
&
c)
{
return
max (max(a,b), c);
//
uses the template version even for ints
}
//
because the following declaration comes
//
too late:
//
maximum of two int values
inline
int
const
&
max (
int
const
&
a,
int
const
&
b)
{
return
a
<
b
?
b : a;
}
昨天晚上建立了这个博客。主要想把关于自己学习C++的知识、人生的感悟、还有从网上看到的好东西等等都放在这里。但建立的时候为博客的名字,我和老婆绞尽脑汁。想的名字不是太俗,就是太怪。于是我们就想到问问我两岁半的儿子,正处于睡意懵懂中的儿子大声说:“宁帅!”。哈哈。这个是儿子给自己起的名字。好就叫这个了。至于“健康、快乐、勇敢”是我们对他的希望。