问题
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