Custom ordered set give “invalid operator<” of find(…)

好久不见. 提交于 2019-12-11 23:53:30

问题


Have a issue when I'm trying to find element in a custom ordered set.

File: c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree
Line: 1746

Expression: invalid operator<

I need a set of strings where the elements are ordered accordingly my needs.

Comparator object:

struct OrderComparator {
public:
    static map<string,int> valueOrder;

    bool operator()( const string lhs, const string rhs ) {
        map<string,int>::iterator resultLhs,resultRhs;
        resultLhs = valueOrder.find(lhs);
        resultRhs = valueOrder.find(rhs);
        if (resultLhs == valueOrder.end() || resultRhs == valueOrder.end())
        {
            return false;
        }
        else {
            bool result = resultLhs->second <= resultRhs->second;
            return result;
        }
    }

    static map<string,int> create_map()
    {
        map<string,int> m;
        m["A"] = 1; 
        m["B"] = 2;
        m["C"] = 3;
        m["D"] = 4;
        return m;
    }
};

Comparator is working fine!

But when I'm trying to search in the set getting mentioned error.

typedef set<string, OrderComparator> TREESET_CMP;
...
TREESET_CMP::iterator it = myTree.find(obj); <-fails
...

Will be glad if some one can tell me why this is happening and how to fix it.


Full working Mini Example:

    #include "stdafx.h"
#include <string>
#include <set>
#include <map>
#include <iterator>
#include <algorithm>
using namespace std;
#include <stdio.h>
#include <tchar.h>

struct OrderComparator {
public:
    static map<string,int> valueOrder;

    bool operator()( const string lhs, const string rhs ) {
        map<string,int>::iterator resultLhs,resultRhs;
        resultLhs = valueOrder.find(lhs);
        resultRhs = valueOrder.find(rhs);
        if (resultLhs == valueOrder.end() || resultRhs == valueOrder.end())
        {
            return false;
        }
        else {
            bool result = resultLhs->second <= resultRhs->second;
            return result;
        }
    }

    static map<string,int> create_map()
    {
        map<string,int> m;
        m["A"] = 1; 
        m["B"] = 2;
        m["C"] = 3;
        m["D"] = 4;
        return m;
    }
};
map<string,int> OrderComparator::valueOrder = OrderComparator::create_map();

typedef set<string, OrderComparator> TREESET_CMP;

int _tmain(int argc, _TCHAR* argv[])
{
    TREESET_CMP myTree;
    myTree.insert("B");
    myTree.insert("C");
    myTree.insert("A");

    TREESET_CMP::const_iterator it = myTree.find("A");
    system("PAUSE");

}

回答1:


Your comparator can be this:

bool operator()( const string &lhs, const string &rhs ) {
    map<string,int>::iterator resultLhs,resultRhs;
    resultLhs = valueOrder.find(lhs);
    resultRhs = valueOrder.find(rhs);
    if (resultLhs == valueOrder.end()) return false;
    if (resultRhs == valueOrder.end()) return true;

    return resultLhs->second < resultRhs->second;
}

You can replace 2 lines to:

if (resultRhs == valueOrder.end()) return false;
if (resultLhs == valueOrder.end()) return true;

If you want strings that do not exist in your map to be sorted before that do.




回答2:


Your comparison doesn't define a strict weak ordering

A strict weak ordering must have these invariants (quoted from the link above)

  • Irreflexivity f(x, x) must be false.
  • Antisymmetry f(x, y) implies !f(y, x)
  • Transitivity f(x, y) and f(y, z) imply f(x, z).
  • Transitivity of equivalence Equivalence (as defined above) is transitive: if x is equivalent to y and y is equivalent to z, then x is equivalent to z. (This implies that equivalence does in fact satisfy the mathematical definition of an equivalence relation.)

Yours fails at least Irreflexivity (comparing an object to itself must be false) and Antisymmetry (if x is less-than y, then y is not less-than x)

Basically, <= is not a valid ordering, because x <= x returns true, which means you can never find an element in the set. To find an element the set looks for an element with the property !cmp(key, element) && !cmp(element, key) but that can never work for your ordering.

The simplest fix might be to change <= to <, but there could be other problems.




回答3:


Try declaring your comparison method to be const and to use const references for the arguements. The first fix is to ensure that you can call your method with constant versions of your OrderComarator the second fix is to avoid copying.

bool operator()( const string& lhs, const string& rhs ) const {


来源:https://stackoverflow.com/questions/15253999/custom-ordered-set-give-invalid-operator-of-find

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!