以下代码在
VC6下编译通过,并且运行良好。其功能为禁止STL map自动排序
struct FIFO
{
bool operator()(const CComBSTR &s1, const CComBSTR &s2) const
{
return true;
}
};
map<type1,type2,FIFO> m;
m["bob"]=1;
m["frank"]=2;
m["louie"]=3;
for( iter=m.begin(); iter!=m.end(); iter++)
{
Cout<<m[i]<<endl;
}
程序输出为:
3 2 1
但是在
.NET 下无法编译。原因是。Net中在插入数据时,用到以下代码
template
<class _Pr, class _Ty1, class _Ty2> inline
bool __CLRCALL_OR_CDECL _Debug_lt_pred(_Pr _Pred, const _Ty1& _Left, const _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);
}
其中
_Pred为对容器中的两个元素进行大小比较,从以上程序可以看出,如果比较算子始终返回真,则.NET将抛出异常_DEBUG_ERROR2,报告“invalid operator<”。
解决办法:
将比较函数用下面的形式代替:
bool
g_ComFlag=false;
CComBSTR g_s1(0);
CComBSTR g_s2(0);
struct
FIFO
{
bool operator()(const CComBSTR &s1, const CComBSTR &s2) const
{
if(g_s1==s2&&g_s2==s1)
g_ComFlag=true;
else
{
g_s1=s1;
g_s2=s2;
g_ComFlag=false;
}
return g_ComFlag;
}
};
则
map程序运行良好,结果和VC6下一致。其原理就是记住刚刚比较的两个值,如果还是继续比较该值,则返回不同的比较结果,从而避开.NET的判断逻辑。对于微软的这一做法,不知道是否符合ISO C++标准,但是这样做更严格了些。
待考虑的:
1.这里用了全局变量来规避.NET关于判断“<”操作符是否有效的策略,可以说是一种无可奈何的选择,不是最佳方案,其实如果要实现不排序的容器,可以用vector<pair<>>。
2.全局变量,线程安全问题。