今天在VS中遇到一个十分诡异的事情,先看下面这个简单的程序:

1
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
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
class cmp
{
public:
	bool operator()(long long l, long long r)
	{
		//~ 此间内容可略去不看。
		//~ 如果l和r含有的digits完全相同则返回false,
		//~ 如125 vs. 512
		char tmp1[1024], tmp2[1024];
		sprintf(tmp1,"%ld",l);
		sprintf(tmp2,"%ld",r);
		sort(tmp1, tmp1+strlen(tmp1));
		sort(tmp2, tmp2+strlen(tmp2));
		if (!strcmp(tmp1, tmp2))
		{
			return false;
		}
		return true;
	}
};
int main(int argc, char* argv[])
{
	set<long long,cmp > Set;
	int a[15];
	Set.insert(1);
	Set.insert(2); //~ 此处疯狂
	return 0;
}

  程序在这个地方跑偏了,弹出这么个东西


  可是set的key_compare我一直都是这么用的啊。把程序拷到Linux下面用g++就一切正常。望达人指教。

更新

  Johnny同学给的贴文中提到了,一个predicate对于任两个参数a,b不能返回两个true,即pred(a, b)和pred(b, a)不能同时返回true,这是strict weak规则决定的。代码为证:

1
2
3
4
5
6
7
8
9
10
template<class _Pr, class _Ty1, class _Ty2> inline
    bool __CLRCALL_OR_CDECL _Debug_lt_pred(_Pr _Pred, _Ty1& _Left, _Ty2& _Right,
        const wchar_t *_Where, unsigned int _Line)
    {    // test if _Pred(_Left, _Right)  and _Pred is strict weak ordering
    if (!_Pred (_Left, _Right))
        return (false);
    else if (_Pred(_Right, _Left))
        _DEBUG_ERROR2("invalid operator<", _Where, _Line);
    return (true);
    }

  即是说,在调试时(特指Visual Studio的debug模式),bool _Debug_lt_pred()模板函数会对pred(a, b)的返回结果进行检查。如果pred(a, b)返回false没有问题。但如果其返回true,那么_Debug_lt_pred还会对pred(b, a)进行检查,若也返回true就会触发assert(有上图为证)。
  对于本文最初的代码,为了通过的_Debug_lt_pred的检查,我可以:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class cmp
{
public:
	bool operator()(long long l, long long r)
	{
		//~ ……
		if (!strcmp(tmp1, tmp2))
		{
			return false;
		}
                else
		        return l < r;
	}
};

这样就保证了cmp::(long long, long long)不会返回“两个true”

Tags: .
你好!除了代码,此处没有多少原创之物,皆为本人搜集、整理、总结之记录与心得,欢迎转载分享!转载时请尽量注明出处,将不胜感激。祝你健康、快乐!
Home

RFC: Request For Comments. Orz..

Name(required)
Mail (required),(will not be published)

RFC: Request For Comments. Orz..

Website(recommended)