Re: why not implicit operator !=()?
On 2012-03-16 14:42, Michael wrote:
On Thursday, March 15, 2012 3:42:09 PM UTC-5, Daniel Kr?gler wrote:
... that the compiler doesn't also go ahead and implicitly define
operator !=() for you?
Please no! First, this would silently change the semantics of existing
programs.
Can you provide an example of this?
struct SomeType
{
bool operator==(const SomeType& rhs) const { return false; }
};
#include <iostream>
#include <type_traits>
template <class T>
auto f(T t, int) -> decltype((t != t, void()))
{
std::cout << "has !=" << std::endl;
}
template <class T>
auto f(T t, ...) -> void
{
std::cout << "has not !=" << std::endl;
}
int main() {
SomeType s;
f(s, 0);
}
Consider now that you run this program for a C++11 compiler which
outputs "has not !=". Later we switch to the compiler version C++1x that
implicitly declares !=. Note that the source code is completely
unchanged. Now the runtime behaviour is silently different. Or-course we
also can easily construct examples that failr during compile-time, but
it is important to realize that a give source code has now a completely
different meaning - that should not happen!
and the ==/!= example has already been mentioned in
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2210.html
But they were simply too late for C++11. IMO extending defaulted
functions to
==
!=
<
<=
=
swap
would be a great idea. But it is important to get the semantics right: I
expect that if I write
The other relational operators could be a bit tricky unless you said
they were all based on operator< being defined (a la std::rel_ops).
Otherwise, it could be a bit confusing.
Yes, that would be a reasonable approach - but the contract has to be
defined clearly.
swap(), well, hmm... The effects of an implicit swap() are a little
less clear to me.
Memberwise swap under the swappable requirements, that is as if in
function would have
using std::swap;
swap(this->member1, rhs.member1);
....
swap(this->memberN, rhs.memberN);
There is still a problem with that approach, because it can only
reasonably work, if we have
#include <utility>
in scope. Arguably this introduces a nasty coupling between core
language and library (swap). I see no good solution for this at the moment.
Another more severe problem
to solve would be a mixture of free and member functions. Consider:
struct SomeType
{
int a, b;
bool operator!=(const SomeType& rhs) const = default;
// return (a == rhs.a)&& (b == rhs.b) ??
} s1, s2;
bool operator==(const SomeType& lhs, const SomeType& rhs) { return
lhs.a
== rhs.a; }
// User says: SomeType::b is no member contributing to ==
I had considered that situation. My naive not-a-language-lawyer little
mind had resolved this by making a simple rule: Try to resolve "a!=b"
first by looking for operator!=() - failing that, look for operator==()
and invert the result. After that, whatever happens, happens.
The problem is that != and == can be non-member functions. Where does
the lookup happen? If one TU adds operator!=, the other does not this is
easy to get wrong for the compiler. To prevent subtle runtime problems
to happen, I suggest the following rule:
1) The corresponding operator needs to be defaulted within the
"contributing" class type. This means that everyone
2) Any following user-provided operator overload with the corresponding
type within the namespace of the type should cause the program to be
ill-formed.
Unfortunately these examples reveal some serious problems to solve.
I don't know about "serious"... I see little here that doesn't already
have some precedence within the language.
Please refer to at least one example of "some precedence". If this has
happened it was (or is) a serious problem. Note that the original
implicit move member specification had caused similar problems. The new
rules are not perfect but they have not the same drastic consequences as
the original ones. Further, move semantics is just an optimization case
of copying. But for != we don't have a similar role: Its is an
independent operation of its own right.
Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]