Topic: auto" operators syntax
Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Sun, 9 Jul 2006 15:14:56 CST Raw View
Andrei Polushin wrote:
> Hi,
>
> Most user-defined operators should have well-known semantics, so they
> are implemented by pattern, written so many times by many people.
> It might be quite annoying for experts, and error-prone for novices.
>
> I propose to allow operators with "auto" modifier, so that compiler is
> able to provide predefined implementation for them.
>
> It looks like the following:
>
> class A {
> int first;
> int second;
> public:
> A(int first, int second) auto;
>
> A& operator+=(const A& a) auto;
> static A operator+(const A& a, const A& b) auto;
>
> A& operator++() auto;
> A operator++(int) auto;
>
> bool operator==(const A& a) const auto;
> bool operator!=(const A& a) const auto;
>
> bool operator<(const A& a) const auto;
> bool operator>(const A& a) const auto;
> bool operator>=(const A& a) const auto;
> bool operator<=(const A& a) const auto;
> };
>
> The code to be generated is shown in /*...*/ comments:
>
> class A {
> int first;
> int second;
> public:
> A(int first, int second) auto;
> /*
> : first(first), second(second) {}
> */
>
> A& operator+=(const A& a) auto;
> /*
> first += a.first;
> second += a.second;
> return *this;
> */
>
> static A operator+(const A& a, const A& b) auto;
> /*
> A tmp = a;
> tmp += b;
> return tmp;
> */
>
> A& operator++() auto;
> /*
> ++first;
> ++second;
> return *this;
> */
>
> A operator++(int) auto;
> /*
> A tmp = *this;
> operator++();
> return tmp;
> */
>
> bool operator==(const A& a) const auto;
> /*
> return first == a.first
> && second == a.second
> ;
> */
>
> bool operator!=(const A& a) const auto;
> /*
> return !(*this == a);
> */
>
> bool operator<(const A& a) const auto;
> /*
> return first < a.first
> || first == a.first && second < a.second
> ;
> */
>
> bool operator>(const A& a) const auto;
> /*
> return a < *this;
> */
>
> bool operator>=(const A& a) const auto;
> /*
> return !(*this < a);
> */
>
> bool operator<=(const A& a) const auto;
> /*
> return !(*this > a);
> */
> };
>
>
> In addition, the same syntax should be allowed for main():
>
> int main() auto;
> /*
> Do what I mean
> */
>
I don't see what you mean for main.
Anyway, most of these "auto" operators are meaningless, and would never
be useful.
A much more useful system would be the automatic implementation of some
operators in terms of others.
For instance, += in terms of + and =, or + in terms of
copy-construction and +=.
Often, we get a class of objects on which an order relation is defined
: < <= == != >= > must be defined; usually in terms of a single cmp()
function which returns a negative, zero or positive value.
But, IMHO it doesn't require a core language change:
The strangely recurring template patterns used on a few well-chosen
template base classes would work well and have much more meaningful
semantics:
#include <iostream>
template <class T>
class Comparable {
int cmp(const T& other) const {
return static_cast<const T&>(*this).cmp(other);
}
public:
bool operator <(const T& other) const {
return cmp(other)<0;
}
bool operator <=(const T& other) const {
return cmp(other)<=0;
}
bool operator ==(const T& other) const {
return cmp(other)==0;
}
bool operator !=(const T& other) const {
return cmp(other)!=0;
}
bool operator >=(const T& other) const {
return cmp(other)>=0;
}
bool operator >(const T& other) const {
return cmp(other)>0;
}
};
template <class T,class Scalar>
/* base requirement : T must support a T::add(Scalar) method.
Rationale : T::add is a better choice than T::operator+=, because it
gives the freedom to redefine operator+= (and other operators),
independently in the T class.
Scalar must have a constructor supporting 1 as argument.
*/
class Incrementable {
T& that() {return static_cast<T&>(*this);}
const T& that() const {return static_cast<const T&>(*this);}
public:
T operator +(Scalar value) const {
T new_object(that());
new_object.add(value);
return new_object;
}
T& operator +=(Scalar value) {
that().add(value);
return that();
}
T& operator ++() {
that().add(Scalar(1));
return that();
}
T operator ++(int) {
T new_object(that());
++that();
return new_object;
}
};
/* you can also write a Decrementable class implementing - -= and --
and a class combining Incrementable and Decrementable features.
*/
/* You can also write an Additionable class for classes which support
self addition (i.e. T& operator+(const T&,const T&) ), in that case ++
will not be defined.
*/
class Value:public Comparable<Value>,public Incrementable<Value,int> {
public:
int cmp(const Value& other) const {return value-other.value;}
void add(int incr) { /* Note : It could even be a virtual function !
*/
value+=incr;
}
int value;
Value(int val):value(val) {}
};
int main() {
Value v0(42),v1(53);
std::cout << (v0<v1) << (v0<=v1) << (v0==v1) << (v0!=v1) << (v0>=v1)
<< (v0>v1) << "\n";
v0++;
v0+=10;
std::cout << (v0<v1) << (v0<=v1) << (v0==v1) << (v0!=v1) << (v0>=v1)
<< (v0>v1) << "\n";
std::cout << ((++v0)+3).value << "\n";
}
Of course, you're free to define your own operator set classes.
In real life ... The same operators can have different semantics on
different classes.
Addition is a good example.
Sometimes, a class can be added a scalar (e.g. random iterators).
But, sometimes the class can be added to itself (e.g. matrixes).
In that case, there should be a template base class for "matrix-style
semantics", and another for "scalar addition semantic", more like the
example given above.
With your proposal, we must stick with a single "universal semantic",
that would impose a single view on the proper semantics of operators.
IMHO, it would be a better idea to write once all these useful template
base classes, and perhaps add them to the boost library... Or, if they
reveal to be very useful, there could be a Technical Report containing
them.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Manfred von Willich" <manfred@techniroot.co.za>
Date: Fri, 30 Jun 2006 16:04:06 CST Raw View
Andrei Polushin wrote:
> I propose to allow operators with "auto" modifier, so that compiler is
> able to provide predefined implementation for them.
Sounded good at first
> int main() auto;
> /*
> Do what I mean
> */
until I decided that you were pulling our collective leg. (Actually,
operators == and != would be candidates for auto, defined in terms of
the same operators of base class(es) and all members, combined with &&
and || respectively.)
Manfred
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Andrei Polushin" <polushin@gmail.com>
Date: Sat, 1 Jul 2006 09:39:59 CST Raw View
ThosRTanner wrote:
> Andrei Polushin wrote:
>> class A {
>> int first;
>> int second;
>> public:
>> A(int first, int second) auto;
>> /*
>> : first(first), second(second) {}
>> */
> Well, I can sort of see this, but I write very few classes where the
> only private data members are those initialised by the constructor.
I didn't mean /private/, but /any/ members, listed in declaration order
as constructor parameters, to be assigned to respective members.
> There's probably some sort of argument for just having
> A(...) auto; // Equivalent to a(int first_, int second_) :
> // first(first_), second(second_)
This seems to be more error-prone in case when we'll add third member.
And it's hard for documentation tool.
>> A& operator+=(const A& a) auto;
>> /*
>> first += a.first;
>> second += a.second;
>> return *this;
>> */
> This is not necessarily an intuitive implementation - OK for complex,
> but for other things?
Well, agreed here: it's contradictious. Should we allow only
operator+() to be auto, but require user to provide operator+=()
explicitly? This is the way of C# (but in reverse order).
> You should have also listed all the standard arithmetic operators.
>
> <snip>
>> A& operator++() auto;
>> /*
>> ++first;
>> ++second;
>> return *this;
>> */
> I cannot believe this to be the case for any class with more than one
> data member. I think A& operator++() { *this += 1; return *this } might
> be more useful.
It seems to be more correct, thank you.
>> bool operator<(const A& a) const auto;
>> /*
>> return first < a.first
>> || first == a.first && second < a.second
>> ;
>> */
> Umm. This doesn't seem to be compatible with your ++.
But it's OK with your correction.
> Anyway, IIRC, there are some templates in boost that allow you to do
> that sort of thing.
Yes, and those templates are "curiously recurring", which is neither
simple nor safe pattern - would you recommend them for novices?
Anyway, I can do it manually.
--
Andrei Polushin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Andrei Polushin" <polushin@gmail.com>
Date: Sat, 1 Jul 2006 09:41:37 CST Raw View
Manfred von Willich wrote:
> Andrei Polushin wrote:
>> I propose to allow operators with "auto" modifier, so that compiler is
>> able to provide predefined implementation for them.
>
> Sounded good at first
>
>> int main() auto;
>> /*
>> Do what I mean
>> */
>
> until I decided that you were pulling our collective leg.
Not at all. Actually, I /mean/ there are too many upcoming proposals
involving the keyword "auto", so we may expect such oddity sometimes.
This was a sort of self-criticism.
By the way, should there be a room for implementation-defined humor
in the standard?
> (Actually, operators == and != would be candidates for auto, defined
> in terms of the same operators of base class(es) and all members,
> combined with && and || respectively.)
Yes, base classes are implied as "members".
But I think it's better to define operator!=() as { !operator==() } -
it looks clearer.
--
Andrei Polushin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Manfred von Willich" <manfred@techniroot.co.za>
Date: Sun, 2 Jul 2006 12:55:52 CST Raw View
Andrei Polushin wrote:
> Manfred von Willich wrote:
> > until I decided that you were pulling our collective leg.
>
> Not at all. Actually, I /mean/ there are too many upcoming proposals
> involving the keyword "auto", so we may expect such oddity sometimes.
> This was a sort of self-criticism.
>
> By the way, should there be a room for implementation-defined humor
> in the standard?
Okay, I am glad the intent I read into your suggestion was a
misinterpretation. Humor? Yes, I think we need lots of that
navigating around all the restrictions implicit in debating changes to
a well-established language.
> > (Actually, operators == and != would be candidates for auto, defined
> > in terms of the same operators of base class(es) and all members,
> > combined with && and || respectively.)
>
> Yes, base classes are implied as "members".
Thanks. I'm still a little vague on some of the terminology.
> But I think it's better to define operator!=() as { !operator==() } -
> it looks clearer.
This opens a whole new can of worms (not that it shouldn't be opened).
C++ allows (and requires) so many intuitively related concepts to be
defined independently, such as copy-ctor and assignment, const and
non-const versions of a member function, operators + and +=, etc.
Your suggestion has the advantage that you can define ==, and then get
!= as an auto. But this would be inconsistent with the many other
cases that already have a compiler-defined version - for example, a
copy ctor that combines the default ctor and assignment would have been
more generally useful than using the member ctors. Besides, one might
argue that != shouldn't be given second-class status.
One also has to think through the defined behaviour if the operators
concerned return a non-bool (e.g. Boost's tribool). Depending on the
semantics of &&, ||, !, ==, != etc. of the member objects, this might
become tricky. I suspect that with tribool this would make no
difference, but this will not be the case for all classes. It is
necessary to determine whether these non-bool operators could be used,
whether the return values would first be converted to bool (to allow
use of the built-in operators like &&) etc. Then, too, one must
realize that the semantics of most operators is actually free to
immense lattitude. Think of std::cout::operator<<(...) - it has
nothing to do with "left shift".
If safe, intuitively obvious "auto" definitions were more clearcut, I
would lend more support. However, I think that it probably makes more
sense to tackle the issue of unifying definitions of semi-redundant
related operators first, though probably difficult at this late stage.
Even my suggestion for == and != suffers from the shortcoming of having
to rely on effectively unrelated operators (&& and ||).
Manfred
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Andrei Polushin" <polushin@gmail.com>
Date: Thu, 29 Jun 2006 17:20:51 CST Raw View
Hi,
Most user-defined operators should have well-known semantics, so they
are implemented by pattern, written so many times by many people.
It might be quite annoying for experts, and error-prone for novices.
I propose to allow operators with "auto" modifier, so that compiler is
able to provide predefined implementation for them.
It looks like the following:
class A {
int first;
int second;
public:
A(int first, int second) auto;
A& operator+=(const A& a) auto;
static A operator+(const A& a, const A& b) auto;
A& operator++() auto;
A operator++(int) auto;
bool operator==(const A& a) const auto;
bool operator!=(const A& a) const auto;
bool operator<(const A& a) const auto;
bool operator>(const A& a) const auto;
bool operator>=(const A& a) const auto;
bool operator<=(const A& a) const auto;
};
The code to be generated is shown in /*...*/ comments:
class A {
int first;
int second;
public:
A(int first, int second) auto;
/*
: first(first), second(second) {}
*/
A& operator+=(const A& a) auto;
/*
first += a.first;
second += a.second;
return *this;
*/
static A operator+(const A& a, const A& b) auto;
/*
A tmp = a;
tmp += b;
return tmp;
*/
A& operator++() auto;
/*
++first;
++second;
return *this;
*/
A operator++(int) auto;
/*
A tmp = *this;
operator++();
return tmp;
*/
bool operator==(const A& a) const auto;
/*
return first == a.first
&& second == a.second
;
*/
bool operator!=(const A& a) const auto;
/*
return !(*this == a);
*/
bool operator<(const A& a) const auto;
/*
return first < a.first
|| first == a.first && second < a.second
;
*/
bool operator>(const A& a) const auto;
/*
return a < *this;
*/
bool operator>=(const A& a) const auto;
/*
return !(*this < a);
*/
bool operator<=(const A& a) const auto;
/*
return !(*this > a);
*/
};
In addition, the same syntax should be allowed for main():
int main() auto;
/*
Do what I mean
*/
--
Andrei Polushin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "ThosRTanner" <ttanner2@bloomberg.net>
Date: Fri, 30 Jun 2006 07:54:27 CST Raw View
Andrei Polushin wrote:
> Hi,
>
> Most user-defined operators should have well-known semantics, so they
> are implemented by pattern, written so many times by many people.
> It might be quite annoying for experts, and error-prone for novices.
They have well defined semantics in certain situations, and in those
situations, I agree the lack of compiler support is really aggravating.
> I propose to allow operators with "auto" modifier, so that compiler is
> able to provide predefined implementation for them.
>
> It looks like the following:
>
> class A {
> int first;
> int second;
> public:
> A(int first, int second) auto;
>
> A& operator+=(const A& a) auto;
> static A operator+(const A& a, const A& b) auto;
>
> A& operator++() auto;
> A operator++(int) auto;
>
> bool operator==(const A& a) const auto;
> bool operator!=(const A& a) const auto;
>
> bool operator<(const A& a) const auto;
> bool operator>(const A& a) const auto;
> bool operator>=(const A& a) const auto;
> bool operator<=(const A& a) const auto;
> };
>
> The code to be generated is shown in /*...*/ comments:
>
> class A {
> int first;
> int second;
> public:
> A(int first, int second) auto;
> /*
> : first(first), second(second) {}
> */
Well, I can sort of see this, but I write very few classes where the
only private data members are those initialised by the constructor.
There's probably some sort of argument for just having
A(...) auto; //Equivalent to a(int first_, int second_) :
first(first_), second(second_)
>
> A& operator+=(const A& a) auto;
> /*
> first += a.first;
> second += a.second;
> return *this;
> */
This is not necessarily an intuitive implementation - OK for complex,
but for other things?
You should have also listed all the standard arithmetic operators.
<snip>
> A& operator++() auto;
> /*
> ++first;
> ++second;
> return *this;
> */
I cannot believe this to be the case for any class with more than one
data member. I think A& operator++() { *this += 1; return *this } might
be more useful.
> bool operator<(const A& a) const auto;
> /*
> return first < a.first
> || first == a.first && second < a.second
> ;
> */
Umm. This doesn't seem to be compatible with your ++.
Anyway, IIRC, there are some templates in boost that allow you to do
that sort of thing.
>
> In addition, the same syntax should be allowed for main():
>
> int main() auto;
> /*
> Do what I mean
> */
How on earth is the compiler meant to work out what you want to do?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]