如何实现C++聚合结构的(中)相等运算符?
有时我有这样的结构 --
struct aggregate1 {
std::string name;
std::vector<ValueT> options;
size_t foobar;
// ...
};
-- 其中(内)相等简单地定义为所有成员的(内)相等: lhs_name == rhs_name && lhs_options == rhs_options && lhs_foobar == rhs_foobar
。
实现这一点的“最佳”方法是什么? (最好是:(运行时-)效率、可维护性、可读性)
operator==
就operator!=
而言operator!=
而言operator==
的==
和!=
的单独实现- 作为成员函数还是作为自由函数?
请注意,这个问题仅涉及(内)相等操作,因为比较 (<
, <=
, ...) 对于这样的聚合体。
Sometimes I have structs such as this --
struct aggregate1 {
std::string name;
std::vector<ValueT> options;
size_t foobar;
// ...
};
-- where (in)equality is simply defined as (in)equality of all members: lhs_name == rhs_name && lhs_options == rhs_options && lhs_foobar == rhs_foobar
.
What's the "best" way to implement this? (Best as in: (Runtime-)Efficiency, Maintainability, Readability)
operator==
in terms ofoperator!=
operator!=
in terms ofoperator==
- Separate implementations for
==
and!=
- As member or as free functions?
Note that this question is only about the (in)equality ops, as comparison (<
, <=
, ...) doesn't make too much sense for such aggregates.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我会这样做,但可能会将operator==定义移动到cpp文件中。将运算符!=保留为内联
记住首先比较最有可能不同的成员变量,以便其余的成员变量被短路并且性能更好。
I would do this but maybe move operator== definition to cpp file. Leave operator!= to be inline
Remember to compare member variables that are most likely to differ first so the rest are short-circuited and performance is better.
成员函数或自由函数是一个品味问题,在我看来,单独编写
==
和!=
的实现似乎很无聊,而且容易出错(您可能会忘记一个成员)两个运算符之一,并且需要时间才能注意到),而不会在效率方面增加任何内容(调用另一个运算符并应用!
的成本可以忽略不计)。该决定仅限于“用
operator!=
实现operator==
更好还是相反?在我看来,从可维护性/可读性/效率角度来看是一样的;为了保持一致性,我只建议在任何地方都以相同的方式进行操作,唯一需要使用其中一个作为“基本运算符”的情况是当您知道这一点时。 ,在结构中包含的类型中,该运算符比其否定更快,但我不知道什么时候会发生这种情况。
Member or free function is a matter of taste, and writing separate implementations of
==
and!=
seems to me boring, error-prone (you may forget a member in just one of the two operators, and it will take time to notice) without adding anything in terms of efficiency (calling the other operator and applying!
has a negligible cost).The decision is restricted to "is it better to implement
operator==
in terms ofoperator!=
or the contrary?In my opinion, in terms of maintainability/readability/efficiency it's the same; I'd only recommend to do it in the same way everywhere for the sake of consistency. The only case where you'd want to prefer to use one or the other as the "base operator" is when you know that, in the types contained in your structure, that operator is faster than its negation, but I don't know when this could happen.
在 C++20 中,实现相等和不等运算符可以像将
operator==
声明为default
一样简单:如果只有
operator==
是假设,a!=b
根据重载解析被解释为!(a==b)
,因此不需要为运算符提供显式重载!=
。我认为默认
operator==
作为隐藏友元更好,因为它适用于引用包装的对象:在此示例中,
operator==
没有为std::reference_wrapper
,但参数相关查找 (ADL) 可以选择隐藏友元,其操作数隐式转换为S const &
。但请注意,::operator==(rs,rs)
仅当operator==
被定义为自由函数时才起作用,因为限定名称不会触发 ADL 。In C++20, implementing equality and inequality operators can be as simple as declaring
operator==
asdefault
:If only
operator==
is provided,a!=b
is interpreted as!(a==b)
according to overload resolution, so there is no need for providing an explicit overload foroperator!=
.I would argue that defaulting
operator==
as a hidden friend is preferable because it works with reference-wrapped objects:In this example,
operator==
is not defined forstd::reference_wrapper<S>
, but argument-dependent lookup (ADL) can select the hidden friend with operands implicitly-converted toS const &
. Notice, however, that::operator==(rs,rs)
will only work ifoperator==
is defined as a free function because ADL is not triggered for qualified names.恕我直言,以朋友的身份实现并实现
operator==
(例如,某些 STL 算法将依赖于此),并且operator!=
应实现为等于的否定操作员。IMHO, implement as friends and implement the
operator==
(some STL algorithms will rely on this for example) and theoperator!=
should be implemented as the negation of the equals operator.(-:自我回答:-)
我想强调聚合 WRT 效率的一个方面:
op==
和op!=< 的评估顺序/code> 与(平均)性能无关。
假设现在单独实现,并给出两个极端 (a-eq) 所有子元素相等和 (b-neq) 所有子元素不相等,我们有以下情况:
operator==
:需要比较所有子元素以返回 trueoperator!=
:需要比较所有子元素以返回 falseoperator==
:确定第一个子元素不相等后返回 falseoperator!=
:确定第一个子元素后返回 true不相等由于无论哪种方式,平均性能都是相同的,至少对我来说,根据
op==
实现op!=
似乎更自然,因为它我觉得实施平等行动更自然。(-: Self answer :-)
I would like to highlight one aspect of aggregates WRT efficiency:
The order of evaluation of
op==
andop!=
is irrelevant for (average) performance.Assuming separate implementations for now and given the two extremes (a-eq) all subelements equal and (b-neq) all subelements inequal, we have these cases:
operator==
: Needs to compare all sub elements to return trueoperator!=
: Needs to compare all sub elements to return falseoperator==
: Returns false after 1st sub element is determined inequaloperator!=
: Returns true after 1st sub element is determined inequalSince performance on average is the same either way it seems -- at least to me -- more natural to implement
op!=
in terms ofop==
, as it feels more natural to me to implement the equality op.