在此示例中,将两个向量与<运算符进行比较将得出Integer类上定义的运算符<,每个元素被调用两次。但是,将两个向量与==运算符进行比较时,不会发生这种情况。
List<MyInterface>
此代码显示:
#include<iostream>
#include<vector>
class Integer {
public:
Integer(int value) : m_value(value) {}
friend bool operator<(const Integer& lhs, const Integer& rhs);
friend bool operator==(const Integer& lhs, const Integer& rhs);
private:
int m_value;
};
bool operator<(const Integer& lhs, const Integer& rhs) {
std::cout << lhs.m_value << " < " << rhs.m_value << '\n';
return lhs.m_value < rhs.m_value;
}
bool operator==(const Integer& lhs, const Integer& rhs) {
std::cout << lhs.m_value << " == " << rhs.m_value << '\n';
return lhs.m_value == rhs.m_value;
}
int main()
{
std::vector<Integer> ivec1 {1,2,3};
std::vector<Integer> ivec2 {1,2,3};
std::cout << (ivec1 < ivec2) << '\n';
std::cout << (ivec1 == ivec2) << std::endl;
return 0;
}
为什么会这样?
答案 0 :(得分:10)
如果a < b
返回false
,它不会告诉您是否b < a
,您必须进行测试。这是因为std::vector
的逐元素排序可以为一对a, b
元素产生三个结果:
a < b
,向量比较将返回true
。b < a
,向量比较将返回false
。因此必须比较两个方向。通过向班级添加标识数据,您可以更清楚地看到这一点:
#include<iostream>
#include<vector>
class Integer {
public:
Integer(int value, char tag) : m_value(value), m_tag(tag) {}
friend bool operator<(const Integer& lhs, const Integer& rhs);
friend bool operator==(const Integer& lhs, const Integer& rhs);
private:
int m_value;
char m_tag;
};
bool operator<(const Integer& lhs, const Integer& rhs) {
std::cout << lhs.m_value << ' ' << lhs.m_tag << " < " << rhs.m_value << ' ' << rhs.m_tag << '\n';
return lhs.m_value < rhs.m_value;
}
bool operator==(const Integer& lhs, const Integer& rhs) {
std::cout << lhs.m_value << ' ' << lhs.m_tag << " == " << rhs.m_value << ' ' << rhs.m_tag << '\n';
return lhs.m_value == rhs.m_value;
}
int main()
{
std::vector<Integer> ivec1 {{1, 'a'} ,{2, 'a'}, {3, 'a'}};
std::vector<Integer> ivec2 {{1, 'b'} ,{2, 'b'}, {3, 'b'}};
std::cout << (ivec1 < ivec2) << '\n';
std::cout << (ivec1 == ivec2) << std::endl;
return 0;
}
这将产生:
1 a < 1 b
1 b < 1 a
2 a < 2 b
2 b < 2 a
3 a < 3 b
3 b < 3 a
0
1 a == 1 b
2 a == 2 b
3 a == 3 b
1
答案 1 :(得分:4)
为了找到traces.append(go.Scatter(
x=X,
y=Y,
text=feature,
mode='markers',
opacity=0.7,
marker={'size': 15,
'line': {'width': 0.5,
'color': 'white'}},
name=feature))
和ivec1
的字典顺序,该实现查找第一个索引ivec2
,其中i
或ivec1[i] < ivec2[i]
为这将确定顺序。
请注意,如果ivec2[i] < ivec1[i]
为假,则需要进行两次比较。特别地,上述情况留下了两种可能性,即“ ivec1[i] < ivec2[i]
和ivec1[i]
比较等效”和“ ivec2[i]
”。这个决定是需要进行第二次比较的地方。
一旦找到这样的索引ivec2[i] < ivec1[i]
,实现就可以停止比较。但是在您的示例中,所有条目的比较结果都是相同的,因此必须对每对条目进行两次比较。
答案 2 :(得分:4)
这是由于C ++当前处理比较的设计存在缺陷。他们正在c++2a中修复它;我不知道它是否可以解决vector
,但基本问题将得到解决。
首先是问题。
std::vector
的{{1}}基于每个元素<
。但是<
不能胜任这项工作。
如果您有两个元素<
和a
,要按字母顺序对元组b
进行排序,您需要执行以下操作:
a,b
通常,如果要按字典顺序订购N个元素的集合,则需要对if (self.a < other.a)
return true;
if (other.a < self.a)
return false;
return self.b < other.b;
进行2N-1次调用。
这早已为人所知,这就是<
返回具有3种值的整数的原因:strcmp
表示较小值,-1
表示相等值,而0
大于(或通常小于或等于零的值)。
您可以这样做:
+1
这最多需要auto val = compare( self.a, other.a );
if (val != 0) return val;
return compare( self.b, other.b );
调用集合中的每个元素N
。
现在,解决方法。
c++2a添加了宇宙飞船比较运算符compare
。它会返回一个可以比较的大于或小于零的类型,其确切类型会通告该操作提供的保证。
这类似于C的<=>
,但可用于支持C的任何类型。此外,有strcmp
个函数使用std
(如果可用),否则使用<=>
和<
等来模拟它们。
假设将向量的要求重写为使用==
,则带有<=>
的类型将避免双重比较,而每个<=>
最多仅进行一次<=>
的字典顺序调用std::vector
时为{1}}。