Eyz*_*uky 51 c++ operator-overloading
我已经operator<
为某个对象实现了.从逻辑上讲,如果!(a < b)
和!(b < a)
它的意思a == b
.
这是自动推断的吗?==
如果我只实施,我可以使用<
吗?
小智 68
由于以下几个原因,C++无法自动推断出这种情况:
operator<
,因此类型可能不一定定义a operator<
.
operator==
无法自动定义operator<
operator<
不需要比较它的参数.程序员可以为其类型定义运算符,以便为其参数执行几乎任何操作.
!(a < b) && !(b < a)
等效的陈述a == b
可能不一定是真的.如果您想要一个operator==
类型的功能,只需自己定义一个.这不是很难:)
// For comparing, something like this is used
bool operator==(const MyType& lhs, const MyType& rhs)
{
// compare (or do other things!) however you want
}
// ... though it's not the only thing you can do
// - The return type can be customised
// - ... as can both of the arguments
const MyType& operator==(int* lhs, const MyType* const rhs)
{
return lhs;
}
Run Code Online (Sandbox Code Playgroud)
phu*_*clv 47
它无法推断==
,<
因为并非所有类型都是有序的,例如std::complex
.是2 + 3i > 1 + 4i
不是?
此外,即使在那些通常命令你仍然不能推断从平等类型>
或<
,例如IEEE-754的NaN
double n = std::numeric_limits<double>::quiet_NaN();
std::cout << "NaN == NaN: " << (n == n) << '\n';
std::cout << "NaN < NaN: " << (n < n) << '\n';
std::cout << "NaN > NaN: " << (n > n) << '\n';
std::cout << "NaN != NaN: " << (n != n) << '\n';
Run Code Online (Sandbox Code Playgroud)
除了最后一个,它们都会返回错误
Jon*_*nas 12
C++不会自动推断出这一点.对operator>
,operator<=
和operator>=
,你可以使用std::rel_ops
; 这只需要operator<
.然而,它并没有提供operator==
在以下方面operator<
.你可以这样做:
template <class T>
bool operator==(T const& lhs, T const& rhs)
{
return !((lhs < rhs) or (rhs < lhs));
}
Run Code Online (Sandbox Code Playgroud)
请注意:!((lhs < rhs) or (rhs < lhs))
并且!(lhs < rhs) and !(rhs < lhs)
在数学上是等效的.
Arn*_*gel 12
从逻辑上讲,如果!(a <b)和!(b <a)则表示== b.c ++会自动推断出来吗?如果我只实现了,我可以使用==
用其他人用数学术语表达的内容:假设你有一个operator <
返回bool
并定义严格的弱顺序,并实现operator ==
为返回!(a < b) && !(b < a)
,那么这个运算符定义了与给定的严格弱顺序一致的等价关系.但是,C++既不需要operator <
定义严格的弱顺序,也不operator ==
需要定义等价关系(尽管许多标准算法sort
可能隐含地使用这些运算符并且需要严格的弱顺序rsp.等价关系).
如果你想根据你operator <
的严格弱顺序定义所有其他关系运算符,Boost.Operators可以为你节省一些输入.
因为它很容易被滥用的operator <
通过偶然通过使用它不符合标准算法的要求,例如std::sort
,std::lower_bound
等等,我建议定义operator <
无论是作为一个严格的弱势整理或根本没有.CodesInChaos给出的示例是一个部分顺序,它不符合严格弱顺序的"无法比较的传递性"要求.因此,我建议用不同的名称来调用这种关系,例如bool setLess(const MySet &, const MySet &)
.
资料来源:
编译器不会推断==
从<
.
你可以用一个简单的例子来检查:
#include <iostream>
struct A {
A(int r):i{r}{}
int i;
};
bool operator<(A const & a1, A const& a2) {
return a1.i < a2.i;
}
int main(int argc, char* argv[]) {
A a1{2};
A a2{3};
if(a1 == a2) {
std::cout << "equals\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC
给你这个错误:
main.cpp:20:11: error: no match for 'operator==' (operand types are 'A' and 'A')
if(a1 == a2) {
Run Code Online (Sandbox Code Playgroud)
std::rel_ops
命名空间中定义了模板,这些模板是自动定义缺失的运算符.
它没有根据您的意愿定义基于less运算符的相等运算符.
这仍然非常有用; 如果你定义less运算符和相等运算符,你将免费获得其他比较运算符.
正如许多人所说,不,你不能,编译器也不应该.
这并不意味着从一个人到另一个人并不容易.<
==
boost ::运营商试图让它变得简单.使用它并完成.
如果你想自己做,那么只需要一些代码来重新实现boost为你提供的功能:
namespace utility {
namespace details {
template<class...>using void_t=void;
template<template<class...>class Z, class, class...Ts>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = ::utility::details::can_apply<Z,void,Ts...>;
}
namespace auto_operators {
template<class T, class U>
using less_r = decltype( std::declval<T const&>() < std::declval<U const&>() );
template<class T, class U>
using can_less = ::utility::can_apply<less_r, T, U>;
struct order_from_less {
template<class T, class U>
using enabled = std::enable_if_t<
std::is_base_of<order_from_less, T>{}
&& std::is_base_of<order_from_less, U>{}
&& can_less<T, U>{},
bool
>;
template<class T, class U>
friend enabled<U,T>
operator>(T const& lhs, U const& rhs) {
return rhs < lhs;
}
template<class T, class U>
friend enabled<U,T>
operator<=(T const& lhs, U const& rhs) {
return !(lhs > rhs);
}
template<class T, class U>
friend enabled<T,U>
operator>=(T const& lhs, U const& rhs) {
return !(lhs < rhs);
}
};
struct equal_from_less:order_from_less {
template<class T, class U>
using enabled = std::enable_if_t<
std::is_base_of<order_from_less, T>{}
&& std::is_base_of<order_from_less, U>{}
&& can_less<T, U>{} && can_less<U,T>{},
bool
>;
template<class T, class U>
friend enabled<U,T>
operator==(T const& lhs, U const& rhs) {
return !(lhs < rhs) && !(rhs < lhs);
}
template<class T, class U>
friend enabled<U,T>
operator!=(T const& lhs, U const& rhs) {
return !(lhs==rhs);
}
};
}
Run Code Online (Sandbox Code Playgroud)
以上只需要写一次,或者从#include
提升中获得相同的cose .
一旦你有了提升,或者上面的提升,就像这样简单:
struct foo : auto_operators::equal_from_less {
int x;
foo( int in ):x(in) {}
friend bool operator<( foo const& lhs, foo const& rhs ) {
return lhs.x < rhs.x;
}
};
Run Code Online (Sandbox Code Playgroud)
和foo
目前拥有上定义的排序和比较操作.
int main() {
foo one{1}, two{2};
std::cout << (one < two) << "\n";
std::cout << (one > two) << "\n";
std::cout << (one == two) << "\n";
std::cout << (one != two) << "\n";
std::cout << (one <= two) << "\n";
std::cout << (one >= two) << "\n";
std::cout << (one == one) << "\n";
std::cout << (one != one) << "\n";
std::cout << (one <= one) << "\n";
std::cout << (one >= one) << "\n";
}
Run Code Online (Sandbox Code Playgroud)
实例.
所有这一切的一点是,C++不,作为一种语言,假设<
手段>
,并>=
与==
所有的意义.但是你可以编写一个库,让你可以使用已<
定义的类型,并且添加一个简单的基类会突然使所有其他操作定义为零运行时成本.
答案是否定的,你只需要一个简单的测试
struct MyType{
int value;
};
bool operator < (MyType& a, MyType& b)
{
return a.value < b.value;
}
int main(int argc, char* argv[])
{
MyType a = {3};
MyType b = {4};
if (a == b)
std::cout << "a==b" << std::endl;
if (a < b)
std::cout << "a < b" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
g ++ 4.8.2抱怨:
main.cpp:在函数'int main(int,char**)'中:
main.cpp:16:11:错误:'operator =='不匹配(操作数类型是'MyType'和'MyType')
但是有一些类似于C++的东西,检查这个c ++概念:比较
它说:
equiv(a,b),一个等价于!comp(a,b)&&!comp(b,a)的表达式
归档时间: |
|
查看次数: |
8983 次 |
最近记录: |