Topic: proposal: postfix increment/decrement syntax
Author: lars_skiba@web.de (Lars Skiba)
Date: Sun, 16 Feb 2003 19:59:36 +0000 (UTC) Raw View
There's is no obviuos reason, why the keywords postfix and prefix
keywords should be in a namespace. I would prefer a syntax like that
operator++() prefix;
operator++() postfix;
The compiler would generate two methods with differant name, so there is
no need for a parameter, which reduce the performance (a little bit).
Sorry for my bad english,
Lars Skiba
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 6 Feb 2003 00:54:10 +0000 (UTC) Raw View
> > Ken@Alverson.net ("Ken Alverson") wrote (abridged):
> > > Is this a problem that's even worth solving?
> Dave Harris wrote:
> > Yes. In my view this is exactly the kind of language change the next
> > revision should be considering - to make C++ easier to learn and use.
>
witless@attbi.com (Witless) wrote
> Then we should consider making it possible to automate the derivation
> of related functions. The difference between the declaration of the
> prefix and postfix increment operators is usually only of interest to
> a class author. The class user usually does not care about the
> function prototypes. Since we use classes much more than we implement
> them, and the confusion can be resolved by reference to the standard
> it appears to be a small problem.
>
> However, the fact a UDT postfix operator can be something other than
> { typeof (*this ); tmp( *this ); ++tmp; return tmp; } can be
> extremely confusing to the class user. It is even worse if
> operator+(T lhs, T rhs) is not built upon operator+=(T lhs, T rhs).
> So the language should provide a mechanism to generate the dependent
> function.
Maybe it makes sense to do these two things together:
* State that when the user defines the prefix version, but not the
postfix version, the compiler writes the postfix version (in the
same way it writes assignment and default constructors). The
compiler's version is equivalent to
sometype rval(*this); ++*this; return rval;
except for two things:
1) There is no sequence point at the "call" to this.
2) The compiler can elide the copy.
This ought to allow the compiler to evaluate the postfix increment
for UDTs the same way that it does for built-in types: it could
copy the value and then increment it (as in the code above), or
it could simply use the value as-is and wait for the next sequence
point before it does the increment.
* State that having the user define the postfix version is deprecated.
Together, these two things would help to reduce (eliminate?) the
"postfix penalty." You know what I mean -- currently the postfix
version has to return by value, which means unneccesary copying even
if that value is not used. I think this is currently true even if
the postfix version is inline, because the as-if rule says that the
copy needs to be created and destroyed. But removing that sequence
point might give compilers an opportunity to optimize in ways that
are currently illegal.
(Any compiler writers want to confirm or deny this?)
class foo {
foo& operator++();
foo operator++(int) { foo r(*this); ++*this; return r; }
};
class bar {
bar& operator++();
// operator++(int) not defined by user
// Compiler defines operator++(int) automatically.
// Equivalent to the version in foo (including the call to
// operator++) except that it might not do the copy.
};
int main() {
foo f;
f++; // Must call foo::operator++(int),
// which creates and then destroys a copy of f
bar b;
b++; // Might optimize to a call to bar::operator++()
// which does not need to do a copy
};
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 6 Feb 2003 00:54:28 +0000 (UTC) Raw View
ark@research.att.com (Andrew Koenig) wrote
> I think that any proposed change to how pre/postfix operators are
> defined needs to address what I think is a far more important problem,
> which is that the types of the postfix operators, as presently
> defined, are a mirage. For simplicity in the following discussion,
> I'm going to use non-member operators, but the same argument applies
> to members.
>
> Consider:
>
> class X {
> // ...
> };
>
> X& operator++(X&); // prefix
> X operator++(X&, int); // postfix
// When you need pointer to postfix, use this one instead:
X postfix_increment(X&x) { return x++; }
> For example, this behavior is a problem because it makes it impossible
> for a single pointer to contain the address of either prefix of postfix
> operator++, even if those operators happen to return the same type
> (which, in this example, they don't).
But you can use the address of this surrogate instead. Viola!
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Sat, 1 Feb 2003 20:47:02 +0000 (UTC) Raw View
ark@research.att.com (Andrew Koenig) wrote (abridged):
> It should be clear that the type of a pointer to prefix operator++
> would be X& (*)(X&), but what about postfix operator++? The answer is
> apparently X (*)(X&, int). In other words, that "int," which is there
> originally as a syntactic device, finds its way into the type system.
That is exactly what I would expect. Why do you think that type is a
mirage?
> For example, this behavior is a problem because it makes it impossible
> for a single pointer to contain the address of either prefix of postfix
> operator++, even if those operators happen to return the same type
> (which, in this example, they don't).
Why is that a problem? It's never been a problem for me in practice.
Prefix and postfix operators do such different things - as you point out,
they have different return types - so there's no a prior reason to insist
pointers to them be the same.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Dirk.Schreib@t-online.de ("Dirk Schreib")
Date: Tue, 28 Jan 2003 19:06:20 +0000 (UTC) Raw View
"Andrew Koenig" <ark@research.att.com> wrote
> Consider:
>
> class X {
> // ...
> };
>
> X& operator++(X&); // prefix
> X operator++(X&, int); // postfix
>
> It should be clear that the type of a pointer to prefix operator++
> would be X& (*)(X&), but what about postfix operator++? The answer is
> apparently X (*)(X&, int). In other words, that "int," which is there
> originally as a syntactic device, finds its way into the type system.
What about
// I personally don't like the 'std::' on reserved names, but...
X& std::prefix operator++(X&); // std::prefix is optional
X std::postfix operator++(X&); // new postfix style
X operator++(X&, int); // old style could still be supported
If both postfix operator are present, this could be
1) illegal
2) supported and x++ will call the new one.
Dirk
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: musiphil@bawi.org (KIM Seungbeom)
Date: Tue, 28 Jan 2003 19:35:38 +0000 (UTC) Raw View
Witless wrote:
>
> Then we should consider making it possible to automate the derivation of related
> functions. The difference between the declaration of the prefix and postfix
> increment operators is usually only of interest to a class author. The class
> user usually does not care about the function prototypes. Since we use classes
> much more than we implement them, and the confusion can be resolved by reference
> to the standard it appears to be a small problem.
>
> However, the fact a UDT postfix operator can be something other than { typeof
> (*this ); tmp( *this ); ++tmp; return tmp; } can be extremely confusing to the
> class user. It is even worse if operator+(T lhs, T rhs) is not built upon
> operator+=(T lhs, T rhs). So the language should provide a mechanism to
> generate the dependent function.
>
> Note that this would be beneficial in three senses. First, the class author
> would usually have less to do. Second, the class user would have less to worry
> about when using related functions. Third, the implementation would be able to
> perform many of the optimizations available for fundamental types that cannot be
> applied to user-defined types.
I also think that we should not have had two distinct operators, prefix
++ and postfix ++, but only one ++, whose behaviour depending on the
form of usage. They look the same, and I've never seen a case where the
obvious implementation of the postfix operator (in terms of the prefix)
was not satisfactory. Why not define once, and use in two ways?
On the other hand, it is not always clear whether + should be
implemented in terms of += or vice versa. In many cases + is implemented
in terms of +=, because defining += is simpler, but consider the matrix
multiplication where defining * is simpler than defining *=.
So in these cases the choice should be left to the author, I think.
--
KIM Seungbeom <musiphil@bawi.org>
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Sat, 25 Jan 2003 21:02:15 +0000 (UTC) Raw View
Ken@Alverson.net ("Ken Alverson") wrote (abridged):
> Foo operator++(std::postfix);
Sounds good, provided there is also a
Foo operator++(std::prefix);
> Is this a problem that's even worth solving?
Yes. In my view this is exactly the kind of language change the next
revision should be considering - to make C++ easier to learn and use.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: allan_w@my-dejanews.com (Allan W)
Date: Sat, 25 Jan 2003 21:05:28 +0000 (UTC) Raw View
Ken@Alverson.net ("Ken Alverson") wrote
> [Problem description]
> C++ allows the user to overload both the prefix and postfix increment
> and decrement operators, and for lack of a better way to differentiate
> the two creates a function signature containing an extra, unused int
> parameter to separate prefix and postfix. This is all fine and good,
> however it's hard to explain or remember which form has the int
> parameter - new users are confused, and even long time users forget
> which is which from time to time.
As you probably know, if there's no particular reason to use the
postfix form, you should normally use the prefix form for user-defined
types. The reason is that prefix can usually return a reference to
self, while postfix must return a copy of self by value (even if that
value is not used).
Also, the prefix form is the one that uses the more "natural"
notation (i.e. no int parameter).
You can use this (coincidence?) to help you remember which is which.
struct foo {
foo &operator++(); // Prefix -- the "normal" form.
foo operator++(int); // Postfix -- special notation for special needs
};
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: witless@attbi.com (Witless)
Date: Sun, 26 Jan 2003 20:09:58 +0000 (UTC) Raw View
Dave Harris wrote:
> Ken@Alverson.net ("Ken Alverson") wrote (abridged):
> > Foo operator++(std::postfix);
>
> Sounds good, provided there is also a
>
> Foo operator++(std::prefix);
>
> > Is this a problem that's even worth solving?
>
> Yes. In my view this is exactly the kind of language change the next
> revision should be considering - to make C++ easier to learn and use.
Then we should consider making it possible to automate the derivation of related
functions. The difference between the declaration of the prefix and postfix
increment operators is usually only of interest to a class author. The class
user usually does not care about the function prototypes. Since we use classes
much more than we implement them, and the confusion can be resolved by reference
to the standard it appears to be a small problem.
However, the fact a UDT postfix operator can be something other than { typeof
(*this ); tmp( *this ); ++tmp; return tmp; } can be extremely confusing to the
class user. It is even worse if operator+(T lhs, T rhs) is not built upon
operator+=(T lhs, T rhs). So the language should provide a mechanism to
generate the dependent function.
Note that this would be beneficial in three senses. First, the class author
would usually have less to do. Second, the class user would have less to worry
about when using related functions. Third, the implementation would be able to
perform many of the optimizations available for fundamental types that cannot be
applied to user-defined types.
Extending this concept to cover the other relationships for fundamental types
that cannot be expressed for user-defined types would increase all three of the
above benefits.
Some examples include:
definition of arithmetic identities and inverses
unary plus derived from addition and zero (additive identity)
subtraction derived from unary minus and addition
increment/decrement derived from addition/subtraction and +/-1
multiplication derived from repeated addition (useful in loop optimization)
relational operators >=, <=, >, and != derived from operator<() and
operator=()
operator&() and operator^() derived from operator|() and operator!()
operator[] derived from operator& and addition of integers
It is bad programming practice to violation the expected relationships among the
operators. Yet there is no way to declare or verify that the relationships to
exist. It is possible to force them to exist, but the process is tedious an
error prone.
We would like to declare the relationships to exist in order to benefit the
users of UDT classes and to enable compiler optimizations. A formal declaration
mechanism would replace the class user's need to scrutinize the class
implementation to determine whether the assumptions are supposed to be valid.
And a formal declaration would permit compiler optimizations to make convenient
assumptions that would be unsafe in the absence of such a declaration.
We would like to verify that the relationships exist to benefit the class author
(find errors) and class user (validate classical usage assumptions). The latter
is especially valuable because it can be difficult to determine whether the
classical assumption about operators are valid. The thoroughness of the
verification is a serious QoI issue if the class author provides an
implementation of the dependent operator.
We would like to force the relationships to exist (generate them) to benefit the
authors, users, and optimizers (implementors). If we can force the
relationships then we automatically get the benefit of declaration and thorough
verification.
---------------------
Note that this suggestion commits the atypical standardization sin. The typical
standardization sin is to suggest a change, usually to notation, without
explaining the benefits or the problem to be solved. So far this suggestion
describes potential benefits without describing the proposed change.
So, while the "=0;" function definition is outstanding in its ugliness, in the
absence of anything more attractive I propose to grow the wart. Declaration and
verification of relationships would appear with an explicit definition as
follows:
T operator++(int) = default { T tmp( *this ); ++tmp; return tmp; }
If it is desirable to distinguish declaration from verification we could use
"=explicit" for declaration and "=restrict" for verification. IMHO overloading
"=default" is (much) better.
Forcing (generation) of dependency relationships would appear with an implicit
definition as follows:
T operator++(int) = default;
In this case the compiler provides a definition selected from a set described by
the language standard This removes the need for the language to support an
algebra over operators and reduces the problem to that of creating the set of
operator dependencies.
Exception specifications should precede because the exception spec is part of
the function declaration while the dependency spec is or is part of the function
definition. For example:
T operator++(int) throw() = default;
As a side note I suggest that we should tolerate ambiguity among the standard
dependencies and let the implementation select the most convenient subset under
the as-if rule. Sometimes it is easier to implement subtraction than it is to
implement addition. So the dependency definitions should provide a rich and
fully symmetrical set of possible defaults.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Ken@Alverson.net ("Ken Alverson")
Date: Mon, 27 Jan 2003 17:02:10 +0000 (UTC) Raw View
"Pete Becker" <petebecker@acm.org> wrote in message
news:3E31BC01.7D10D347@acm.org...
>
> It doesn't help: you still have to remember that the postfix version
is
> the one that takes an argument. (Okay, the name helps a bit). Maybe
> this, though:
>
> operator++(std::postfix)
> operator++(std::prefix)
That is the logical extension of the idea, but I didn't want to suggest
that until I got a reaction on the first change, because I didn't have a
fallback plan for prefix like the typedef for postfix. However, as Mr.
Frey pointed out, "typedef void prefix;" is valid, and complements
"typedef int postfix;" nicely.
So I guess it comes down to:
(A) Is it better to change the signatures to take empty classes (seems
like a cleaner approach, backwards compatibility ignored), or would
handling collisions of unlike signatures be too problematic?
(B) Is the change worth making? I think it is, especially since the
cost to implement (particularly the typedef solution) is low and the
change would be non-invasive and backward compatible. I also think if
the practice has any hope of becoming expected behavior, it has to be
part of the standard. As pointed out, using the class occurs far more
often than implementing, however I don't think that's a reason to avoid
a positive change in readability, and the end user may still be exposed
to it during the course of debugging.
Ken
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: dheld@codelogicconsulting.com ("David B. Held")
Date: Mon, 27 Jan 2003 18:47:57 +0000 (UTC) Raw View
""Ken Alverson"" <Ken@Alverson.net> wrote in message
news:b13k59$416$1@eeyore.INS.cwru.edu...
> [...]
> That is the logical extension of the idea, but I didn't want to suggest
> that until I got a reaction on the first change, because I didn't have a
> fallback plan for prefix like the typedef for postfix. However, as Mr.
> Frey pointed out, "typedef void prefix;" is valid, and complements
> "typedef int postfix;" nicely.
> [...]
struct X
{
typedef void t;
void operator++(t) { }
};
int main() { }
"ComeauTest.c", line 4: warning: declaring a void parameter list with a
typedef is nonstandard
void operator++(t) { }
This issue was discussed on Boost, with respect to generic code, where
an empty parameter list might get generated. It turns out that it would
be useful to be able to define an empty parameter list with a void type,
but this is apparently not legal.
Dave
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Ken@Alverson.net ("Ken Alverson")
Date: Mon, 27 Jan 2003 19:26:32 +0000 (UTC) Raw View
""David B. Held"" <dheld@codelogicconsulting.com> wrote in message
news:v3ass4l1daek1c@corp.supernews.com...
>
> struct X
> {
> typedef void t;
> void operator++(t) { }
> };
>
> int main() { }
>
> "ComeauTest.c", line 4: warning: declaring a void parameter list with
a
> typedef is nonstandard
> void operator++(t) { }
Huh...looks like you're right - I tried MCVC 7 on warning level 4 and
g++ with -Wall before I posted and neither said a thing, so I figured it
must be ok...guess not :)
Ken
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: a9804814@unet.univie.ac.at (Thomas Mang)
Date: Mon, 27 Jan 2003 20:28:40 +0000 (UTC) Raw View
Dave Harris schrieb:
> Ken@Alverson.net ("Ken Alverson") wrote (abridged):
> > Foo operator++(std::postfix);
>
> Sounds good, provided there is also a
>
> Foo operator++(std::prefix);
>
> > Is this a problem that's even worth solving?
>
> Yes. In my view this is exactly the kind of language change the next
> revision should be considering - to make C++ easier to learn and use.
Not necessarily.
It'd be easier for newcomers, certainly, if they only have to deal with
std::prefix syntax/ std::postfix syntax. Once they learn one version and see
occasionally the other one, the trouble can start.
I think it's better having only ONE syntax. Don't misunderstand me, I like
the idea, and if the standard were to invent overloaded operator++/++, I
guess many other favored this too.But currently, it may also well make things
just more complicated.
regards,
Thomas
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Ken@Alverson.net ("Ken Alverson")
Date: Mon, 27 Jan 2003 22:01:12 +0000 (UTC) Raw View
"Witless" <witless@attbi.com> wrote in message
news:3E33FA59.5CA4EA68@attbi.com...
>
> Then we should consider making it possible to automate the derivation
> of related functions. The difference between the declaration of the
> prefix and postfix increment operators is usually only of interest to
a
> class author. The class user usually does not care about the function
> prototypes. Since we use classes much more than we implement
> them, and the confusion can be resolved by reference to the standard
> it appears to be a small problem.
<snip>
> Forcing (generation) of dependency relationships would appear with
> an implicit definition as follows:
>
> T operator++(int) = default;
These two ideas do not have to be mutually exclusive. Consider:
T operator++(std::postfix) = default;
compared to your example. Isn't that more readable?
Ken
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: lars_skiba@web.de (Lars Skiba)
Date: Mon, 27 Jan 2003 22:54:21 +0000 (UTC) Raw View
Daniel Frey wrote:
> X operator++( std_::postfix ) { X nrv( *this ); ++nrv; return nrv; }
Even the standard allows you to implement the postfix operator in this
way, you shouldn't. It's a behavior, which differs from the behavior of
built-in types. You should increment the current object and not the one,
which you'll return. You'll return a *not* incremented object.
--
www.c-plusplus.de
The german C++ Forum
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 27 Jan 2003 22:54:32 +0000 (UTC) Raw View
witless@attbi.com (Witless) wrote (abridged):
> > In my view this is exactly the kind of language change the next
> > revision should be considering - to make C++ easier to learn and use.
Especially if the "typedef void postfix;" thing works and it doesn't even
need a language change.
> Then we should consider making it possible to automate the derivation
> of related functions.
How about:
template <typename T>
struct PostInc {
friend T operator++( T &t, int ) {
T old( t );
++t;
return old;
};
};
class MyClass : public PostInc<MyClass> {
public:
MyClass &operator++();
};
See http://www.boost.org/libs/utility/operators.htm for a development of
this approach. It doesn't need any language changes.
> And a formal declaration would permit compiler optimizations to
> make convenient assumptions that would be unsafe in the absence
> of such a declaration.
Isn't enough that the function definitions be inline?
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: ajo@andrew.cmu.edu ("Arthur J. O'Dwyer")
Date: Mon, 27 Jan 2003 22:55:01 +0000 (UTC) Raw View
On Sun, 26 Jan 2003, Witless wrote:
>
> Extending this concept to cover the other relationships for fundamental types
> that cannot be expressed for user-defined types would increase all three of the
> above benefits.
>
> Some examples include:
> definition of arithmetic identities and inverses
> unary plus derived from addition and zero (additive identity)
These two only make sense in the context of integer types, and only if
there is also an accepted way of referring to a type's arithmetic
identities: T::AdditiveIdentity and T::MultiplicativeIdentity, or
something.
> subtraction derived from unary minus and addition
That's not terribly useful. Usually (IME), unary minus is derived from
subtraction, not the other way around.
> multiplication derived from repeated addition (useful in loop optimization)
Multiplication can't be derived from addition, because multiplication is
_not_ addition, for any application that matters. Consider
realnumber(3.14) * realnumber(2.72) // float multiplication
vect(1,2,3) * vect(4,5,6) // vector multiplication
transform(mat::shiftx, 1) * transform(mat::rotate, 3.14) // compounding
> operator&() and operator^() derived from operator|() and operator!()
First of all, you mean operator~(), not operator!(). And then again this
only works for integer types, and C++ already _has_ several perfectly
good integer types. Any decent bignum library will need to implement
these operations independently for efficiency, and any small project won't
need them at all for this purpose.
> operator[] derived from operator& and addition of integers
This one just doesn't make any sense.
> increment/decrement derived from addition/subtraction and +/-1
> relational operators >=, <=, >, and != derived from operator<() and
> operator=()
These two ideas are the only good ones I've seen, besides the ones that
started this thread:
+ in terms of +=
- in terms of -=
...
| in terms of |=
++(int) in terms of ++(void)
--(int) in terms of --(void)
> So, while the "=0;" function definition is outstanding in its ugliness, in the
> absence of anything more attractive I propose to grow the wart. Declaration and
> verification of relationships would appear with an explicit definition as
> follows:
>
> T operator++(int) = default { T tmp( *this ); ++tmp; return tmp; }
>
> If it is desirable to distinguish declaration from verification we could use
> "=explicit" for declaration and "=restrict" for verification. IMHO overloading
> "=default" is (much) better.
I don't quite follow this part. Surely the Standard would contain this
sort of thing, not user programs?
> Forcing (generation) of dependency relationships would appear with an implicit
> definition as follows:
>
> T operator++(int) = default;
>
> In this case the compiler provides a definition selected from a set described by
> the language standard.
Yes. Okay. I like it, kind of.
But I can't help thinking that a clever template programmer could
implement this sort of thing in vanilla C++ fairly easily.
template <typename T>
T operator ++(const T &t, int dummy)
{
T tmp(t);
++t;
return tmp;
}
Does this compile and work (for the case of ++(int) in terms of ++(void))?
Or better,
#define default_postinc(T) \
T operator ++(const T &t, int dummy) { \
T tmp (t); ++t; return tmp; \
}
...
class MyIntegerType
{
public:
MyIntegerType operator ++(void) {
...
}
default_postinc(MyIntegerType)
};
and similarly for all the rest. Maybe all in a header file somewhere,
which the programmer could include in the projects that needed it.
So on second thought, why bother changing the language?
HTH
-Arthur
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Ken@Alverson.net ("Ken Alverson")
Date: Mon, 27 Jan 2003 22:56:32 +0000 (UTC) Raw View
"Witless" <witless@attbi.com> wrote in message
news:3E33FA59.5CA4EA68@attbi.com...
>
> Then we should consider making it possible to automate the derivation
of related
> functions. The difference between the declaration of the prefix and
postfix
> increment operators is usually only of interest to a class author.
The class
> user usually does not care about the function prototypes. Since we
use classes
> much more than we implement them, and the confusion can be resolved by
reference
> to the standard it appears to be a small problem.
<snip>
> Forcing (generation) of dependency relationships would appear with an
implicit
> definition as follows:
>
> T operator++(int) = default;
These two ideas do not have to be mutually exclusive. Consider:
T operator++(std::postfix) = default;
compared to your example. Isn't that more readable?
Ken
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: Mon, 27 Jan 2003 22:57:05 +0000 (UTC) Raw View
Ken> (B) Is the change worth making?
I think that any proposed change to how pre/postfix operators are
defined needs to address what I think is a far more important problem,
which is that the types of the postfix operators, as presently
defined, are a mirage. For simplicity in the following discussion,
I'm going to use non-member operators, but the same argument applies
to members.
Consider:
class X {
// ...
};
X& operator++(X&); // prefix
X operator++(X&, int); // postfix
It should be clear that the type of a pointer to prefix operator++
would be X& (*)(X&), but what about postfix operator++? The answer is
apparently X (*)(X&, int). In other words, that "int," which is there
originally as a syntactic device, finds its way into the type system.
For example, this behavior is a problem because it makes it impossible
for a single pointer to contain the address of either prefix of postfix
operator++, even if those operators happen to return the same type
(which, in this example, they don't).
--
Andrew Koenig, ark@research.att.com, http://www.research.att.com/info/ark
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Ken@Alverson.net ("Ken Alverson")
Date: Fri, 24 Jan 2003 22:14:07 +0000 (UTC) Raw View
[Problem description]
C++ allows the user to overload both the prefix and postfix increment
and decrement operators, and for lack of a better way to differentiate
the two creates a function signature containing an extra, unused int
parameter to separate prefix and postfix. This is all fine and good,
however it's hard to explain or remember which form has the int
parameter - new users are confused, and even long time users forget
which is which from time to time.
[Proposed solution]
I propose creating an empty class in the standard namespace called
"postfix", which will serve the same purpose as int currently serves.
Thus, the definition:
Foo operator++(int);
would become
Foo operator++(std::postfix);
which is immediately obvious when reading as the postfix version of the
operator. The int syntax would remain for backwards compatibility, and
defining both an "int" and "postfix" version of the operator would be
considered an error.
As far as I can tell, the change would be minimally invasive and it
requires no new keywords, just a new std namespace identifier. In the
event that allowing two different signatures to mean the same thing
would cause too many problems, how about a "typedef int postfix;" in the
standard namespace? While a user could do that currently, for such a
thing to become normal behavior I believe it would have to exist in the
standard.
Comments? Is this a problem that's even worth solving?
Ken
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: petebecker@acm.org (Pete Becker)
Date: Sat, 25 Jan 2003 02:28:04 +0000 (UTC) Raw View
Ken Alverson wrote:
>
> Foo operator++(std::postfix);
>
> which is immediately obvious when reading as the postfix version of the
> operator. The int syntax would remain for backwards compatibility, and
> defining both an "int" and "postfix" version of the operator would be
> considered an error.
>
It doesn't help: you still have to remember that the postfix version is
the one that takes an argument. (Okay, the name helps a bit). Maybe
this, though:
operator++(std::postfix)
operator++(std::prefix)
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: d.frey@gmx.de (Daniel Frey)
Date: Sat, 25 Jan 2003 21:01:01 +0000 (UTC) Raw View
On Fri, 24 Jan 2003 23:14:07 +0100, Ken Alverson wrote:
> [Problem description]
> C++ allows the user to overload both the prefix and postfix increment
> and decrement operators, and for lack of a better way to differentiate
> the two creates a function signature containing an extra, unused int
> parameter to separate prefix and postfix. This is all fine and good,
> however it's hard to explain or remember which form has the int
> parameter - new users are confused, and even long time users forget
> which is which from time to time.
There is an easy way to remember it: the prefix version is the fast, light
version while the postfix version is the "slow" version as it has some
ballast: It needs to copy. This ballast is shown by an additional
parameter. Well, at least this helps me to remember it, YMMV :)
> [Proposed solution]
> I propose creating an empty class in the standard namespace called
> "postfix", which will serve the same purpose as int currently serves.
> Thus, the definition:
>
> Foo operator++(int);
>
> would become
>
> Foo operator++(std::postfix);
>
> which is immediately obvious when reading as the postfix version of the
> operator. The int syntax would remain for backwards compatibility, and
> defining both an "int" and "postfix" version of the operator would be
> considered an error.
The typedef you proposed already solves this problem without further
changes. If you are looking for a way to document you code, may I suggest
*two* typedefs instead? Like this:
namespace std_
{
typedef void prefix;
typedef int postfix;
}
struct X
{
X& operator++( std_::prefix ) { /* INC me */ return *this; }
X operator++( std_::postfix ) { X nrv( *this ); ++nrv; return nrv; }
};
int main()
{
X x;
++x;
x++;
}
> Comments? Is this a problem that's even worth solving?
I don't think so... hope it helps you anyway :)
Regards, Daniel
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]