在STL中,排序是个很重要的话题。

1.algorithm 里的sort()只接收RandomAccessIterator
用于像vector,dequeue的排序

2.像set,map,这种关联式容器,本身就由RBTree维护了有序,只要遍历一遍就行了。

3.而list比较特殊一点,由于只有BidirectionalIterator。而又不本身有序。
所以该容器自带了一个用来排序的函数。

现在有个问题,如果在list里面存的是char*的元素。
那么排序的时候,就会按照指针的大小来排。
而如果我们本来用char*来表达一个字符串的话,这样就不符合要求了。(见下例输出1)

而list.sort有一个带参数的用法。
可以设计一个函数(如下的mycmp),传给list.sort。

这种用法我一直感觉很纠结,因为list.sort的参数是
greater<T>
也就是一个functor(函数对象,函子,仿函数),本质上是一个类。
而把函数名(本质上是个指针)传进去做参数。。。居然也可以。。

从我们使用的语义上来说,似乎是可以的,因为functor传进去了之后,
会调用该类的“()”操作符,也就是我们会把他视作一个函数来使用。
可是明明他们就是不同的东西。。。

这种用法在DEV-C下可以通过。(貌似VS也可以)

在DEV-C下的例子:

#include <iostream>
#include <list>
#include <string.h>
#include <iterator>

using namespace std;

char *ss[] = { "bb" , "aa" , "cc" , "ee" , "dd" } ;

bool mycmp( char *&s1 , char *&s2){
    return strcmp(s1 , s2) == -1 ;
}

int main(){
    list<char*> l(ss , ss + sizeof(ss) / sizeof(char*)) ;
    ostream_iterator<char*> oit(cout , " ") ;//构造输出迭代器 
    copy( l.begin() , l.end() , oit) ;cout<<endl;//输出原序列 
    l.sort() ;//默认的排序,其实是按指针大小排序 
    copy( l.begin() , l.end() , oit) ;cout<<endl;//输出1 
    l.sort(mycmp);//传入函数指针的排序 
    copy( l.begin() , l.end() , oit) ;cout<<endl;//输出2 
    system("pause");
    return 0 ;
}

输出:

bb aa cc ee dd
bb aa cc ee dd
aa bb cc dd ee

可见不带参数的是按指针从小到大排序的。

而这段在VC6里就会报错,即使把mycmp加上ptr_fun的修饰也不行。

主要是list的sort参数实在太奇怪了。
STL里面有很多函数提供两个版本,其中一个以默认方式进行比较,
另一个版本可以允许传入一个functor,以该functor进行比较。

而这个list.sort直接限定死了传进去的是greater<T>

比如,我们直接设计一个functor

struct c{
    operator()(char *&s1 , char *&s2){
        return strcmp(s1,s2) == -1 ;
    }
};

后面调用:l.sort(c());

编译器会给出下面的信息:

cannot convert parameter 1 from 'struct c' to 'struct std::greater<char *>'
        No constructor could take the source type, or constructor overload resolution was ambiguous

其实就是类型不匹配。。。-_-编译器只认greater这个functor。

虽然我们可以改变greater的实现,但是那样,把代码复制到其他地方,
执行的结果肯定就不一样了。。。

就是这里纠结了很久。。后来终于不小心搞定了,用特化!!

像下面这样:(代码直接从泛化的greater复制过来,做相应修改就可以了)

struct greater<char*> : binary_function<char*, char*, bool> {
    bool operator()(const char*& _X, const char*& _Y) const
        {return (strcmp(_X,_Y) == -1); }
    };

在DEV里面,全特化要求加入 template<>开头,VC里面可以不加。

那么后面直接这样调用就可以了:l.sort(greater<char*>()) ;

这时编译器选择的就不是前面泛化的greater了,就是我们量身定做的char* 的greater。

且慢,在VC6里面还要报错。

error C2934: 'greater<char *>' : template-class-id redefined as a nested 'struct' of '<Unknown>'

又是这个东西。。让我一直没有搞定。。网上也没找到相应的解决方案。

今天突然发现了。。namespace的问题。因为greater是定义在std里面的。。
汗啊。。感觉这报错好没提示性。。于是一改果然可以了。

下面这份代码和前面的差不多。在VC6下运行正常:

相信通过前面的解释能够很容易明白。

#include <iostream>
#include <list>
#include <string.h>
#include <algorithm>
#include <vector> using namespace std; char *ss[] = { "bb" , "aa" , "cc" , "ee" , "dd" } ; namespace std{
struct greater<char*> : binary_function<char*, char*, bool> {
bool operator()(const char*& _X, const char*& _Y) const
{return (strcmp(_X,_Y) == -); }
};
} int main(){
list<char*> l(ss , ss + sizeof(ss) / sizeof(char*)) ;
ostream_iterator<char*> oit(cout , " ") ;
copy( l.begin() , l.end() , oit) ;cout<<endl;
l.sort() ;
copy( l.begin() , l.end() , oit) ;cout<<endl;
l.sort(greater<char*>()) ;
copy( l.begin() , l.end() , oit) ;cout<<endl;
return ;
}

binary_function:

Note: This class has been deprecated in C++11.

This is a base class for standard binary function objects.

Generically, function objects are instances of a class with member function operator() defined. This member function allows the object to be used with the same syntax as a regular function call, and therefore its type can be used as template parameter when a generic function type is expected.

In the case of binary function objects, this operator() member function takes two parameters.

binary_function is just a base class, from which specific binary function objects are derived. It has no operator()member defined (which derived classes are expected to define) - it simply has three public data members that aretypedefs of the template parameters. It is defined as:

1
2
3
4
5
6
template <class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};

上面的greater不继承binary_function也可以正常运行。

要想利用STL list 的sort,还有一种办法,直接在list元素类里面重载   bool operator < 也可以正常运行。

转自:http://hplonline20100103.blog.163.com/blog/static/1361364342010040031155/

VC6.0 list sort出错的更多相关文章

  1. vc6.0连接mysql数据库

    一.MySQL的安装 Mysql的安装去官网下载就可以...最新的是5.7版本.. 二.VC6.0的设置 (1)打开VC6.中选0 工具栏Tools菜单下的Options选项,在Directories ...

  2. VC6.0下string不能用pusk_back,可用+=代替

    2013-09-11 21:14:32 在VS下运行正确的代码,拿到VC6.0下,编译出错,提示: error C2039: 'push_back' : is not a member of 'bas ...

  3. VC6.0代码移植到VS2008运行时乱码问题解决

    转载:http://blog.sina.com.cn/s/blog_6d0cbb030101a3cs.html 问题描述:     之前用VC6.0写过一个OpenGL的程序,后来需要将其放到VS20 ...

  4. VC6.0中重载操作符函数无法访问类的私有成员

    整理日: 2015年03月18日 在 C++ 中,操作符(运算符)可以被重载以改写其实际操作.同时我们可以定义一个函数为类的朋友函数(friend function)以便使得这个函数能够访问类的私有成 ...

  5. VC++6.0打开文件出错的解决办法

    1.下载http://support.microsoft.com/kb/241396里面的一个叫FileTool.exe的文件并解压,解压后是一个vc工程,用vc6.0打开工程,编译,得到FileTo ...

  6. pcre7.0在vc6.0编译

    (0)从http://gnuwin32.sourceforge.net/packages/pcre.htm  (pcre windows)下下载最新的windows平台源代码pcre-7.0-src. ...

  7. VC6.0调试知识大全

    VC6.0调试知识大全 分类: C++ 2010-09-06 21:33 7080人阅读 评论(5) 收藏 举报 debuggingmfcfunctionmenumicrosoftdll My Not ...

  8. Vc6.0头文件的定义

    Vc6.0头文件的定义 #ifndef __HEADER__ #define __HEADER__ int fun(int i); #endif

  9. VC6.0中友元函数无法访问类私有成员的解决办法

    举个例子: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #inclu ...

随机推荐

  1. PHP中的cookie创建取回删除;

    <?php $expire=time()+3600;//设置过期cookie时间 setcookie('yaoyuan',"webyaoyuan",$expire);//se ...

  2. Linux下Tomcat安装、配置

    /etc/profile./etc/profile.d和.bash_profile区别 /etc/profile和/etc/profile.d区别 .bash_profile 是存放用户的全局变量 / ...

  3. codeforces 505C Mr. Kitayuta, the Treasure Hunter(dp)

    题意:有30001个岛,在一条线上,从左到右编号一次为0到30000.某些岛屿上有些宝石.初始的时候有个人在岛屿0,他将跳到岛屿d,他跳跃的距离为d.如果当前他跳跃的距离为L,他下一次跳跃的距离只能为 ...

  4. less编码规范

    Less 编码规范 简介 因为自己最近写css用的比较多还是less,整理了一份less规范, 代码组织 代码按如下形式按顺序组织: @import 变量声明 样式声明 // ✓ @import &q ...

  5. 19个非常有用的Javascript类库

    Blackbird是一款非常酷的JavaScript调试工具,带有一个漂亮的界面显示和过滤调试信息. http://www.gscottolson.com/blackbirdjs/ Treesaver ...

  6. U3D C#脚本的生命周期

    MonoBehaviour是每个脚本的基类. 每个Javascript脚本自动继承MonoBehaviour,使用C#或Boo时,需要显式继承MonoBehaviour. 一开始实例化,直到结束实例被 ...

  7. Beyond Compare 设置打开文件的默认编码

    转载:http://www.note4u.info/archives/360 Beyond Compare 每次打开都会以西欧(windows)打开文件,在有中文的地方,经常出现乱码.但是设置每个文件 ...

  8. Andriod ADT v22.6.2版本中在Mainactivity.java中使用fragment_main.xml中TextView控件对象的问题

    众所周知,我们既可以在 activity_main.xml文件中控制activity中的view,也可以使用java代码的set..()方法控制它.在学习过程中,发现在ADT新版本中,和以前版本有区别 ...

  9. DBA 培训相应内容笔记

    014-12-23 slow hang lock 三种常见性能问题 hang;整个数据库不响应,无法创建新连接. hanganalyze输出. dump文件是否有问题信息, 文件是否有其他信息 工具: ...

  10. 网页icon和文本对齐神技 2016.03.23

    一直以来icon和文本需要对齐都使用vertical-align: middle;的方法,但兼容性不理想.参考了鑫旭大大的博客,终于收获不用vertical-align可以对齐的神技,原博点这里. 代 ...