.NET 中禁止map自动排序

来源:互联网 发布:gis软件 编辑:程序博客网 时间:2024/05/16 20:28
 
以下代码在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.全局变量,线程安全问题。
 
 
原创粉丝点击