{ edits: quoted banner removed. please don't quote the banner. -mod }
There is no such operator in C++.
It's just a combination of two operators: postfix decrement "--" and
greater ">".
That's why this example works.
Try ( x --> 20 ) and you'll get no output in this case;)
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
{ edits: quoted banner removed. please don't quote the banner. -mod }
I don't know where it is defined exactly, but this code is allowed.
while( x-- > 0 )
:)
{ edits: quoted banner removed. please don't quote the banner. -mod }
I think, that what you are talking about is just a "post-decrement" in
combination with a greater-comparsion. Just looks fancy, but isn't
defined anywhere as an special operator.
Try it this way:
while( x-- > 0)
I.e. it's a postfix decrement operator and a greater-than operator.
:D
Uli
--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
I think it was intended as a joke as the parser find int::operator--
and operator>( int, int ) :)
But you wouldn't want to confuse anyone thinking they could actually
write :
#include <iostream>
int main( )
{
int x = 0;
while( x --> 10 ) // x goes to 10
{ std::cout << x << "\n"; }
}
Because in that case, x is going to take a very long time to get
there :)
--
Olivier Grant
--
You missed the subtlety:
while(x-->0)
is compiled as:
post decrement x
compare the undecremented value with 0
now use the decremented value if the comparison was true. OP's code
should output
9 8 7 6 5 4 3 2 1 0
Now try it, and surprise, surprise, that is exactly what is output :)
{ edits: quoted banner removed. please don't quote the banner. -mod }
I may be wrong; that's not strictly an operator, but another way of
writing
while ( x-- > 0 )
--
It's not an operator.
x --> 0
translates as
(x--) > 0
I have missed something?
If s is not an element of an array of 'char const* const' values,
which is usually the case, is (&s + 1) well-defined?
That is, in the following:
int a[1], *p = &a[0] + 1;
int i , *q = &i + 1;
I know that the initializer for p is well-defined, but is that for q
also well-defined?
I read 5.7/5, and almost everything seems to be qualified by
"If the pointer operand points to an element of an array object,"
and I don't find anything about what happens when it does not.
--
Seungbeom Kim
>Derek wrote:
>> I like the little-known operator "-->", also know as "goes to."
>>
>> while( x --> 0 ) // x goes to 0
>> :
>>
>
>And where in the Standard is that defined?
It isn't. Derek is playing on C++'s fairly lax parsing rules that
don't require prefix/postfix operators to be adjacent to the variable
name and don't always require white space between operators.
"x --> 0" is parsed as "x-- > 0".
George
Jed : "Jethro, why don't you show him your gozintas."
Jethro: "Two gozinta two, one. Two gozinta four, two. ..."
--
I think the 20 or so semantically identical replies to this post make
the case pretty well for my suggestion that moderation frequency is
increased by adding new moderators.
Neil Butterworth
struct foo
{
foo()
{
std::printf("(%p)->foo::foo()\n",
(void*)this);
}
~foo()
{
std::printf("(%p)->foo::~foo()\n",
(void*)this);
}
};
foo
make_foo()
{
return foo();
}
int
main()
{
{
foo const& f = make_foo();
std::printf("got a const reference to f(%p)\n",
(void*)&f);
}
return 0;
}
_______________________________________________________________
{ edits: quoted banner removed. please don't quote the banner. -mod }
"-->" is not a operator.
It combines "--" and ">".
"--" has a higher priority than ">".
Of course there is. It is described together with "runs to" operator:
#include <stdio.h>
int main()
{
int x = 10;
while( x -->> 0 ) // x runs to 0
printf("%d ", x);
}
> in the following:
>
> int a[1], *p = &a[0] + 1;
> int i , *q = &i + 1;
>
> I know that the initializer for p is well-defined, but is that for q
> also well-defined?
>
> I read 5.7/5, and almost everything seems to be qualified by
> "If the pointer operand points to an element of an array object,"
> and I don't find anything about what happens when it does not.
5.7, 4: "For the purposes of these operators, a pointer to a nonarray
object behaves the same as a pointer to the first element of an array of
length one with the type of the object as its element type."
--
And they could have been accepted by 20 different moderators. Adding
moderators does not solve the problem. The principle of moderation in
this group is that if you can be bothered to post something on topic
then it will be accepted.
In fact very often apparently similar responses are not identical and
burdening moderators with both knowing what has already been posted and
then making value judgements on whether a new response is actually the
same is a recipe for discontent.
Sometimes we have lots of almost identical responses but they are always
very short and can be quickly scanned by readers.
The delay factor will always exist even if you have carefully picked 24
moderators from 24 different time zones. We go on holiday, fall ill etc.
And C++ expertise has never been a requirement for a moderator. What is
generally required is that they are regular readers of the newsgroup.
The only easy way to identify that is when they are also regular
responders to other people's posts. Of course these people tend to be
reasonably competent with C++
In fact, we do have a documented reason for rejection:
[Already Stated] The article restates the contents of another
article (or articles) already posted to the newsgroup. Such
articles will only be rejected if in the opinion of the moderators
nothing new is added to the discussion.
and I could have rejected some of the seemingly identical responses
if I had processed them. However, rejection is justified only when
the new article is completely redundant, i.e. its content is completely
covered by others already posted, and as Francis mentioned it's not
always easy to determine that. Furthermore, it can help understanding
a lot if the same thing is explained in many different ways.
In addition, I don't think it's fair to reject for [Already Stated]
an article submitted before other articles covering the same thing
are accepted. So, a lot of similar replies waiting in the moderation
queue at the same time all tend to be accepted. This is where more
moderators and more frequent processing could help, but I haven't
seen a lot of cases where it could have actually made a big difference.
--
Seungbeom Kim
> And they could have been accepted by 20 different moderators. Adding
> moderators does not solve the problem. The principle of moderation in
> this group is that if you can be bothered to post something on topic
> then it will be accepted.
Perhaps I haven't made myself clear - I am not suggesting that
moderators reject posts as duplicates. I am suggesting that more
frequent moderation would reduce the number of duplicate posts.
{ Mod terminology factoid: we do have a [Nothing New] rejection reason; see the
page referenced by the link in the banner below. It's distinct from a
[Duplicate] rejection. However, it's seldom used. -mod }
> The delay factor will always exist even if you have carefully picked 24
> moderators from 24 different time zones. We go on holiday, fall ill etc.
Of course. But all other things being equal, the larger the number of
moderators, the less the effect of holidays, illness etc.
Neil Butterworth
As soon as the first such message gets through the moderation queue and
become visible to the general public, it should generally inhibit any
further discussions that cover the exact same points; that's the same
mechanism that makes such duplicate messages less common on unmoderated
newsgroups. I won't prevent duplicate messages, but there will be fewer
or them. The more moderators you have, the sooner that first message is
likely to get processed.
> The delay factor will always exist even if you have carefully picked 24
> moderators from 24 different time zones. We go on holiday, fall ill etc.
It will always exist, but there should, on average, be smaller delays
when there are more moderators.
On Oct 29, 12:13 am, Derek <de...@antiquark.com> wrote:
> while( x --> 0 ) // x goes to 0
it'd better to write the code in this manner :
while (x-- > 0) {do something}
Best
Olaf Krzikalla
Perhaps you missed the other partner of goes to: the ++< operator
And then what about these
while(x-->=0) //goes to and reach there
while(x++<=100) //goes to and reach there II
while(x>>1) //goes to one but in a 'different' way
I mean c'mon, you can't be serious when you speaks '-->' as a 'goes
to' operator. Thats a dirty way to remember a hack/idiom. Why make
things more opaque when it has got a simple meaning: `while(x-->0)';
run the loop by decrementing x until it is zero.
Boy, do I feel stupid. I should have seen that, but the obfuscation
waw very well done.
...and the last value will be -1, unless of course 'x' happens to be
unsigned which will then cause similar effects as the next one.
> while(x++<=100) //goes to and reach there II
...and in the body you will get x==101 as last value, so it's the
dreaded "goes to and let other l337 h4x0rz 0wnz0r your boxen" operator.
> while(x>>1) //goes to one but in a 'different' way
Nope, that one doesn't go anywhere, at least not without some help in the
body of the loop.
> I mean c'mon, you can't be serious when you speaks '-->' as a
> 'goes to' operator. Thats a dirty way to remember a hack/idiom.
And the hack is pretty bad, because seemingly even a well-versed programmer
easily gets them wrong, as you volunteered to demonstrate. ;^)
Cheers & don't try this at home!
Uli
--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Attempting to steer this thread back on topic, I'll mention exception
specifications - very few programmers properly understand their
capabilities and expect too much or too little of them, depending on
who you ask. Usually members of the too much group don't last long,
because they discover they're asking too much and get converted to the
too little group. I'm not sure who came up with the idea that they're
100% useless, but even in their most rudimentary role (as an assert()
that doesn't require you to write out long try-catch blocks for every
function) they are helpful. I heartily disapprove of people who insist
that they are useless without properly understanding them.
Sean Hunt
--
It's hard to know which tricks are obscure enough to count. I find
declarations in if-statements useful:
if (Object *p = get_object())
p->use();
It's concise, and also helps minimise the scope of p, making it harder to
accidentally use it when it is undefined or NULL. It's convenient enough
that I sometimes adding bool conversions to my own classes in order to
use it:
if (Object o = get_object())
o.use();
The correct way to do that is itself probably a trick. Simply adding
operator bool() is a bad idea because it enables conversions to int,
which are scarily general. There is more on this here:
http://www.artima.com/cppsource/safebool.html
std::partition can be handy if you are dealing with raw pointers (is this
dark enough?) Std::erase() will overwrite some pointers with other
pointers, which can lead to memory leaks, but with std::partition every
pointer is preserved.
void predicate_delete( std::vector<int *> &v ) {
std::vector<int *>::iterator i = std::partition(
v.begin(), v.end(), predicate() );
for (std::vector<int *>::iterator j = i; j != v.end(); ++j) {
// delete *j would leave an invalid value in the vector,
// so remove it first.
int *p = *j;
*j = 0;
delete p;
}
v.erase( i, v.end() );
}
Not everyone knows that URLs are valid C++ syntax. Admittedly that's
largely because it's not very useful:
int main() {
http://www.boost.org/
return 0;
}
-- Dave Harris, Nottingham, UK.
The reason many people insist they are useless is another dark hidden
corner of C++. They are checked at runtime.
Believe me, this makes them entirely useless for programs that can't
afford to crash
C++0x will let you mark conversions as explicit. An explicit conversion
to bool will be used when you ask for it, and when you use an object in
a boolean context, such as the if statement above.
--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)
if (Object *p = get_object(), p != 0)
I prefer this style infinitely to if (a == b) or even if ((a == b) !=
0)
> Not everyone knows that URLs are valid C++ syntax. Admittedly that's
> largely because it's not very useful:
>
> int main() {
> http://www.boost.org/
Shouldn't there be a ';' here?
> return 0;
Nope, it is just declaring a label 'http' and then placing a one-line
comment 'www.boost.org/', there is no statement there ;)
JP
Now that's dark-corner-syntax indeed :-)
I find it quite pointless tough. Testing *pointers* as in the example
above in a boolean context seems to be the most normal thing to to in
C++. I find your example more obfuscating than clean.
cheers,
Martin
I don't think you can, here.
Object *p;
if (p = get_object(), p != 0)
would work, and I like that style (it avoids compiler warnings as well
as being more legible to my eyes), but a declaration isn't an
expression -- it can't be used with the comma operator.
Yechezkel Mett
Why don't write ScopeGuard this way:
int main()
{
{
foo const f();
std::printf("got a scope guard f(%p)\n", &f);
}
return 0;
'http' is a label, '//' starts a line-delimited comment. No semicolon
required. What I'm not sure about is whether the following 'return 0;' is
required, at least a switch label must be followed by another one or a
statement.
That said, this hack just made my day. :)
Uli
--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Are you sure? This:
void test() {
int *get();
if (int *p = get(), p != 0)
return;
}
doesn't seem to compile at:
http://www.comeaucomputing.com/tryitout/
> > int main() {
> > http://www.boost.org/
> Shouldn't there be a ';' here?
>
> > return 0;
> > }
It compiles without it. There does need to be a statement after the label,
which is why I included the return.
-- Dave Harris, Nottingham, UK.
--
> (I detest implicit casting)
Casting is, by definition, explicit. The thing that seems to bother you
is not a cast, but the lack of a cast.
Anyway, I don't understand the sentiment. I've seen it mostly on
Usenet, and it makes no sense to me. The whole point of abstract data
types is that you don't have to know exactly how operations on them are
implemented, and the point of generic programming (and duck typing, et
al) is that you should not have to know the exact types involved. If a
type has the feature of being useful in a boolean context, then IMHO,
that feature should be leveraged for brevity and clarity, not avoided
for stupendously subtle and arcane reasons.
> if (Object *p = get_object(), p != 0)
There's an implicit conversion in that code. 0 is a literal int, not a
pointer.
Here's a little guideline I humbly submit to the coding community at
large: When deciding which of two styles is the clearer, tend toward
the shorter.
Excuse my lack of knowledge, but could anyone provide a compiling
example of above code?
Thanks,
Daniel
> Here's a little guideline I humbly submit to the coding community at
> large: When deciding which of two styles is the clearer, tend toward
> the shorter.
Umm. I've never found
while (*p++ = *q++);
a particularly clear implementation of strcpy. But i doubt you could
get anything much shorter.
>>> if (Object *p = get_object(), p != 0)
>> There's an implicit conversion in that code. 0 is a literal int, not a
>> pointer.
> Well, I'd prefer p != null, obviously, but that's not available yet
You don't need a keyword to get a properly typed null pointer.
typedef object_t* object_pointer_t;
if (p != object_pointer_t( )) ...
Or if you prefer:
object_pointer_t const null_object_pointer = object_pointer_t( );
Or if you really want a special null, just so you don't have to typedef
raw pointers:
enum null_t { null };
template<typename T>
bool operator!=(T* const p, null_t) {
typedef T* pointer_t;
return p != pointer_t( );
}
template<typename T>
bool operator!=(null_t, T* const p) {
return p != null;
}
But what's the point of adding the != at all? Why not use the clear,
short, obvious code originally posted?
>> Here's a little guideline I humbly submit to the coding community at
>> large: When deciding which of two styles is the clearer, tend toward
>> the shorter.
> Umm. I've never found
> while (*p++ = *q++);
> a particularly clear implementation of strcpy.
That looks about as clear as any implementation I've seen. The problem
with strcpy is that it's non-intuitive to think of strings as pointers.
> But i doubt you could
> get anything much shorter.
Well, you could remove the whitespace, but I didn't say "always go with
the shortest option." I'm just confused as to why you "detest" implicit
conversions, whereas I find them immensely convenient when used properly.
I didn't mean to be self-important, I actually haven't seen that
construction before. If I do this:
int* getintp() { return 0; }
if( int* i = getintp(), i != 0 )
{
}
then I get "error: expected ')' before ',' token" from gcc 4.3.2.
This compiles though:
int* i;
if( i = getintp(), i != 0 )
{
Because the type of foo is a base class with no virtual destructor
(for efficiency) and there are different types of scope guards
possible.
As I understand it this trick will be made redundant by C++0x's `auto`
keyword.
Some of us even mastered the stuff like templates, object model,
complex I/O, etc.
But what are the most hidden features or tricks or dark corners of C++/
STL that even C++ fans, addicts, and experts barely know?
I am talking about a seasoned C++ programmer (be she/he a developer,
student, fan, all three, etc), who thinks (s)he knows something 99% of
us never heard or dreamed about. Something that not only makes his/her
work easier, but also cool and hackish. After all, C++ is one of the
most used programming languages in the world, thus it should have
intricacies that only a few privileged know about and want to share
with us.
Boost is welcome too!
(Originally, this discussion appeared on
http://stackoverflow.com/questions/1596139/hidden-features-and-dark-corners-of-stl
... and now I want bring it to the de facto authority of C++ and share
their experience with stl )
Thanks
By now probably everyone know this one, but it was a major revelation
for me at the time: when a temporary is assigned to a reference inside
a {} block, it's lifetime is extended to the lifetime of a reference.
That made ScopeGuard possible. ScopeGuard FTW!
Goran.
Here's an example:
#include <stdio.h>
int main()
{
int x = 10;
while( x --> 0 ) // x goes to 0
{
printf("%d ", x);
}
}
--
> By now probably everyone know this one, but it was a major revelation
> for me at the time: when a temporary is assigned to a reference inside
> a {} block, it's lifetime is extended to the lifetime of a reference.
> That made ScopeGuard possible. ScopeGuard FTW!
This is actually not strictly necessary to make ScopeGuard work,
albeit it might be one of the most efficient ways.
And where in the Standard is that defined?
Do you mean something like in the next example?
#include <iostream>
class A
{
public:
A( int a ): a(a)
{
}
int a;
};
class B
{
public:
B(A &a) : a(a)
{
}
A &a;
};
int main()
{
B *b=NULL;
{
A a(5);
b = new B(a);
}
std::cout<<b->a.a<<std::endl;
delete(b);
In the 2005 draft that I just looked at
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf)
see 5.3.2 and 5.9.
-Chris Hopman
2.6 Tokens
2.12 Operators and puntuators
5.3.2 Increment and decrement
5.9 Relational operators
--
Gerhard Menzl
Non-spammers may respond to my email address, which is composed of my
full name, separated by a dot, followed by at, followed by "fwz",
followed by a dot, followed by "aero".
> > int x = 10;
> > while( x --> 0 ) // x goes to 0
> And where in the Standard is that defined?
5.2.6/2 and 5.9/1. :-)
The funny line above could have been written like this with more
common coding conventions:
while (x-- > 0)
Now it should be clear where the bits come from.
--
Maciej Sobczak * www.msobczak.com * www.inspirel.com
The C++ Database Access Library: http://soci.sourceforge.net
{ edits: quoted banner removed. please don't quote the banner. -mod }
it is probably
while( x-- > 0 ) //
Rabin
> But what are the most hidden features or tricks or dark corners of C++/
> STL that even C++ fans, addicts, and experts barely know?
> (Originally, this discussion appeared onhttp://stackoverflow.com/questions/1596139/hidden-features-and-dark-c...
> ... and now I want bring it to the de facto authority of C++ and share
> their experience with stl )
>
I like the top answer there. It is also possible to use such aproach
of emplacing via insert with a single element:
void append(vector<string>& vs, char const* const s)
{
vs.insert(vs.end(), &s, &s + 1); // extra copying required by
push_back is avoided.
It depends how you write it:
while( x-- > 0 )
He's joking. He's actually written
while (x-- > 0)
It's just x-- > 0 ...
I think it's simply a way to write (x--) > 0, and an imho, a confusing
one.
It's a combination of 5.2.6 and 5.10.
--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)
I was thinking the same, but consider this:
while( x-- > 0 )
Such hack can cost companies loads of money, but I can't but smile a
little anyway. See it as one of the dark corners. ;)
In the sections describing the -- and > operators, presumably :-)
Neil Butterworth