写了个快速排序函数模板,但是对于字符串类型是不能排序的,因为在比较大小*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); } |
|
函数特化优先级低,所以不行。
|
|
特化版本比不特化优先级高吧,怎么会低 |
|
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 *的多重含义,而不是什么语法原因。
|