为什么带迭代器的函数为什么不能有特化呢(泛型函数)

C++语言 码拜 10年前 (2015-07-10) 1046次浏览 0个评论
 

写了个快速排序函数模板,但是对于字符串类型是不能排序的,因为在比较大小*p < *i时,应该用strcmp()函数,所以需要再写一个带比较器版本。但是我问老师为什么不直接再写一个针对字符串的特化版本,而要去写一个带比较器版本的,他说迭代器的模板是不能特化的,但是没有解释为什么,请问大神为什么迭代器的模板不能特化呢?是不能特化呢,还是只是为了更好的通用性而不特化呢?谢谢!

//有比较器版本,IT代表迭代器,CMP比较器
template<typename IT, typename CMP>
void sort (IT begin, IT end,CMP cmp) {
...
//代码与下面的差不多
}
//无比较器版本
template<typename IT> //IT 表示迭代器
void sort (IT begin, IT end) {
	IT p = begin;
	IT last = end;
	--last;
	for (IT i = begin, j = last;
		i != j;) {
		while (! (i == p || *p < *i))
			++i;
		if (i != p) {
			swap (*i, *p);
			p = i;
		}
		while (! (j == p || *j < *p))
			--j;
		if (j != p) {
			swap (*j, *p);
			p = j;
		}
	}
	IT it = begin;
	++it;
	if (p != begin && p != it)
		sort (begin, p);
	it = p;
	++it;
	if (it != end && it != last)
		sort (it, end);
}
 
函数特化优先级低,所以不行。
 
引用 1 楼 yshuise 的回复:

函数特化优先级低,所以不行。

特化版本比不特化优先级高吧,怎么会低

25分

首先应该明白,函数模板及其特化,是C++最基础的语言结构。几乎整个STL都是在此基础上写出的源程序【这里可以说唯一例外是C++的TR1标准引入了””调用特征””(call signature)。这个语法概念是个新鲜的东西,其形式是 函数返回类型,之后是用括号包起来的用逗号分隔的形参类型列表(可以为0个形参)。调用特征广泛用于STL的模板定义。 调用特征定义了一个函数的类型,但与传统的函数指针类型的定义不同,调用特征不需要表示“指针”型的星号*。对于熟悉C语言的人猛一看到””调用特征””(call signature)就会纳闷这是什么鬼东西?】

所以,无论是迭代器、比较器、分配器、适配器等等,都是设计STL的先行者们提出的一些编程规范。你照着做或者不照着做,其实都可以。这些东西都是模板这个语法之上的高层的一些设计理念。

结论:不存在“迭代器的模板不能特化”。

下面要问,为什么不推荐通过迭代器的模板特化来实现功能,而是建议用比较器呢? 这个稍微思考就明白:只靠迭代器的不同类型,是不足以区分各种情形的。辨识能力不足。例如,题主是要做快速排序,现在有一大堆字符串(ASCII0串)要排序,迭代器可能是个char*,你敢保证凡是char*的迭代器就是要比较ASCII0串吗? 也许人家就是要做指针值的排序呢。

所以这个语义,应该用比较器明确给出来。对于两个迭代器所指的两个对象,到底该如何做大小的比较。这从逻辑上、语义上比较完美,清晰、易读。

就是这样。

 
是指这样子吗

template<> void sort<char *> (char * first, char * last);

5分

是因为char *的多重含义,而不是什么语法原因。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明为什么带迭代器的函数为什么不能有特化呢(泛型函数)
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!