4月14日学习心得

今天结束了第十六章的学习

16.4

可变参数模板

  一个可变参数模板就是一个接受可变数目的模板函数或模板类。可变数目的参数称为参数包。存在两种参数包:模板参数包,表示零或多个模板参数,函数参数包,表示零或多个函数参数。

template <typename T, typename... Args>
void foo(const T&t,const Args& ...rest)
{
	cout << sizeof...(Args) << endl;
	cout << sizeof...(rest) << endl;
}

可以用sizeof(ARGS)表示类型参数个数,sizeof(args)表示函数参数的数目。

在很多时候可变模板参数的性能要由于initializer_list,而且大多数模板是通过递归方法计算的,注意一定要定义非可变参数的版本,否则最后一个无法处理,将陷入无穷递归中。

template <typename T>
ostream &myprint(ostream &os, const T &t)
{
	return os << t;
}

template <typename T,typename ...Args>
ostream &myprint(ostream &os,const T& t, const Args&... args)
{
	os << t << ",";
	return myprint(os, args...);
}

    包扩展是我们出获取参数包大小外所做的唯一事情。当扩展一个包时,我们还要供应于每个扩展元素的模式,通过省略号(...)触发扩展操作。要注意扩展中的模式会独立地应用于包中的每个元素。

  可以使用std::forward<Args>(args)...来实现参数包的转发。


16.5

模板特例化

  模板特例化是模板的一个特殊版本,本质上来说是一种实例化的特例,指定一个特定的类型做特殊操作,以下是一个例子

template <typename T>
size_t st(const vector<T> & t,const T& aim)
{
	size_t cnt = 0;
	for (auto c : t)
	{
		if (c == aim)
			++cnt;
	}
	return cnt;
}

template <>
size_t st(const vector<const char*> & t, const char* const& aim)
{
	size_t cnt = 0;
	for (auto c : t)
	{
		if (strcmp(c,aim)==0)
			++cnt;
	}
	return cnt;
}

  要注意这种用法最有用的目的就是处理const char* ,这种类型既难转化为string有难转化为T&.

  由于特例化的本质是实例化一个模板,而非重载它。因此,特例化不影响函数匹配。


  为了特例化一个模板,原模板的声明必须在作用域中。而且,在任何使用模板实例的代码之前,特例化的版本声明也必须在作用域中。模板及其特例化本应声明在同一个头文件中。所有同名模板的声明应该放在前面,然后是这些模板的特例化版本。


有时我们会使用部分特例化,即对类内的部分成员特例化,所以函数是不存在特例化的。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页