Topic: need C++ guru: operator precedence


Author: "Bill Wade" <bill.wade@stoner.com>
Date: 1999/03/08
Raw View

Steve Clamage wrote in message <7bp3cr$lf2$1@engnews1.eng.sun.com>...
>..., but in fact the tables don't work right for all
>expressions; the conditional operator ?: in particular needs to
>occupy two different slots in a precedence table.

Someone recently pointed out that you can put ?: in a precedence table with
the assignment operators (right to left binding).  So that

  a op1 b op2 c

means

  a op1 (b op2 c)

whenever both op1 and op2 are either assignment operators or "? stuff :"

I believe they were correct.

In other words the right hand argument to either an assignment or a
conditional may be an assignment or a conditional.  The left hand argument
to both assignment and conditional may not be an assignment or conditional.




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/03/09
Raw View
In article <7c1hdv$23h$1@uuneo.neosoft.com>, Bill Wade
<bill.wade@stoner.com> writes
>In other words the right hand argument to either an assignment or a
>conditional may be an assignment or a conditional.  The left hand argument
>to both assignment and conditional may not be an assignment or conditional.

Maybe, but the associativity is different so I think you still get in a
mess.


Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Stephen.Clamage@sun.com (Steve Clamage)
Date: 1999/03/05
Raw View
Biju Thomas <bijuthom@ibm.net> writes:

>Steve Clamage wrote:
>>
>> "J.Barfurth" <techview@bfk-net.de> writes:
>>
>> >I always relied on code like
>> >    A* p = NULL;
>> >    try
>> >    {
>> >        p = new A();
>> >    }
>> >    catch (..) {}
>>
>> >to leave p at NULL, if the ctor of a throws an exception.
>> >(The catch handlers will often be far away, and p might be a class member)
>>
>> That's an interesting question. I don't find anything in the
>> standard that says a value won't be assigned to p if the A
>> constructor exits via an exception.
>>

>The assignment operator causes the value of rhs to be assigned to the
>lvalue at lhs. I believe this is the meaning of assignment operation in
>C++.

>The value to be assigned to 'p' is not constructed if the constructor
>for 'A' exits via an exception. How can a value be assigned to 'p' if
>the value doesn't exist?

I think you are correct. (And I was hoping something like that was
the answer.) Section 5.3.4 paragraph 17 applies here, I think.
The new-expression does not complete, so the new-expression doesn't
have a value to be assigned.

--
Steve Clamage, stephen.clamage@sun.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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1999/03/06
Raw View
Biju Thomas wrote:
>
> Steve Clamage wrote:
> >
> > "J.Barfurth" <techview@bfk-net.de> writes:
> >
> > >I always relied on code like
> > >    A* p = NULL;
> > >    try
> > >    {
> > >        p = new A();
> > >    }
> > >    catch (..) {}
> >
> > >to leave p at NULL, if the ctor of a throws an exception.
> > >(The catch handlers will often be far away, and p might be a class member)
> >
> > That's an interesting question. I don't find anything in the
> > standard that says a value won't be assigned to p if the A
> > constructor exits via an exception.
> >
>
> The assignment operator causes the value of rhs to be assigned to the
> lvalue at lhs. I believe this is the meaning of assignment operation in
> C++.
>
> The value to be assigned to 'p' is not constructed if the constructor
> for 'A' exits via an exception. How can a value be assigned to 'p' if
> the value doesn't exist?

The value of (*p) is what is not constructed; p itself can be assigned a
value as long as the memory is allocated, resgardless of whether a
correctly constructed 'A' occupies that memory.

However, I wouldn't recommend using that value. Section 5.3.4 p17 says
"If any part of the object initialization described above terminates by
throwing an exception and a suitable deallocation function can be found,
the deallocation function is called to free the memory in which the
object was being constructed ...", so if p is assigned a value, it's
likely to be one that can't be safely dereferenced.


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: jim.hyslop@leitch.com
Date: 1999/03/06
Raw View
In article <7boiqt$h8c$1@news.eunet.ch>,
  "Daniel Grob" <Daniel.Grob@elca.ch> wrote:
[snip]
> Given my example (IC_String *test = new IC_String(fkt())) there is also only
> one allowed ordering:
> 1. fkt()
> 2. IC_String()
> 3. new
> 4. =
>
> Am I missing something?
Yes - you are missing the fact that IC_String(fkt()) *looks* like a function
call, but in fact it is not.  If you were to use the default ctor, your code
would be:

IC_String *test = new IC_String;

No parentheses to make it look like a function call - does this change the
order of what happens? Not in the slightest.

Also, consider that the job of operator new is to (a) call the allocation
function to allocate memory for the object, *then* (b) invoke the constructor
for the object.

How can you possibly invoke the constructor for an object, when no memory has
been allocated for that object??

Jim
Note to recruitment agencies:  I will not refer my friends or colleagues
to you nor do I want to use your services to find me a job.  I stop
reading unsolicited email as soon as I determine it is job-recruitment

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/03/06
Raw View
In article <7boiqt$h8c$1@news.eunet.ch>, Daniel Grob
<Daniel.Grob@elca.ch> writes
>Am I missing something?

Yes. The rules you seek to apply relate to parsing an expression, not to
its evaluation.  Once an expression has been fully parsed the
evaluations can be carried out in any order consistent with the parse
tree.  I.e. a node can only be evaluated when the subtree of which it is
the root has been fully evaluated.

The reason C and C++ grant this freedom (which Java does not) is to
allow high levels of optimisation.

Associativity has only ever been used to determine the order of
evaluation of successive uses of the same operator.  For example:

ans = a/b/c;

requires that a/b be evaluated as the left operand of /c.

however

ans = a/b + b/c;

places no ordering requirement on the two divisions because they do not
interact (even if they are user defined, the only requirement is that
they be evaluated sequentially)



Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Daniel Grob" <Daniel.Grob@elca.ch>
Date: 1999/03/04
Raw View
Hello

This might be a tricky question. I wonder, what you think about it...
If I write the following line of code:

IC_String *test = new IC_String(IC_String::fkt())

where
IC_String is a class
new is the overloaded operator for the IC_String class
fkt() is a simple function returning an long
IC_String(long) is a contstructor for the IC_String class

In what sequence are the functions / operators called?

In my C++ book I see, that a constructor has precedence over the new
operator. So the sequence should be:
1. the function IC_String::fkt()
2. the constructor IC_String()
3. the new operator

But what my compiler does is:
1. the new operator
2. the function IC_String::fkt()
3. the constructor IC_String

On another compiler the sequence is:
1. the function IC_String::fkt()
2. the new operator
3. the constructor IC_String

Now the question:
Who is right? My C++ book? My compiler? The other compiler? Someone else?


Thanx for your answers!

Regards

    Dany




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stephen.Clamage@Eng.Sun.COM (Steve Clamage)
Date: 1999/03/04
Raw View
"Daniel Grob" <Daniel.Grob@elca.ch> writes:

>If I write the following line of code:

>IC_String *test = new IC_String(IC_String::fkt())

>where
>IC_String is a class
>new is the overloaded operator for the IC_String class
>fkt() is a simple function returning an long
>IC_String(long) is a contstructor for the IC_String class

>In what sequence are the functions / operators called?

>In my C++ book I see, that a constructor has precedence over the new
>operator. So the sequence should be:
>1. the function IC_String::fkt()
>2. the constructor IC_String()
>3. the new operator

You are confusing precedence with order of operations.  Precedence
determines only how operations are grouped.  It establishes a
partial ordering, not necessarily a total ordering.

Example:
    f() + g() / h()
Since / has higher precedence than +, the result of the division
must be known before the addition can be performed. But the three
functions can be called in any order. The only other requirements
are that g and h must be called before the division can be performed,
and f must be called before the addition can be performed.  Any
ordering that meets those requirements is acceptable.

In your example, you can't invoke the the constructor until its
argument has been evaluated, so fkt must be called before the
constructor.

The constructor can be invoked only if memory has been allocated
for it to operate on. That means that operator new must be called
before the constructor can be called.

The assignment of a value to "test" can occur only after operator
new has returned a value.

So we have this partial ordering:
    operator new before the constructor
    fkt before the constructor
    operator new before the assignment to test
Any ordering that satisfies those requirements is acceptable.

--
Steve Clamage, stephen.clamage@sun.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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "J.Barfurth" <techview@bfk-net.de>
Date: 1999/03/04
Raw View
Steve Clamage wrote<7bmhfj$s4h$1@engnews1.eng.sun.com>...
>"Daniel Grob" <Daniel.Grob@elca.ch> writes:
>
>>If I write the following line of code:
>
>>IC_String *test =3D new IC_String(IC_String::fkt())

[...]

>>In what sequence are the functions / operators called?

[...]

>
>So we have this partial ordering:
>    operator new before the constructor
>    fkt before the constructor
>    operator new before the assignment to test
>Any ordering that satisfies those requirements is acceptable.
>

Does this really mean there is no specified order 'constructor before the
assignment to test' ?

I always relied on code like
    A* p =3D NULL;
    try
    {
        p =3D new A();
    }
    catch (..) {}

to leave p at NULL, if the ctor of a throws an exception.
(The catch handlers will often be far away, and p might be a class member=
)

Was I just LUCKY ??

- Sorry for cutting 'most all the quotes (my server wont let me post
anything where there's more quotes than own text)

-- J=F6rg Barfurth
(techview@bfk-net.de, jbarfurth@vossnet.de)
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Stephen.Clamage@eng.sun.com (Steve Clamage)
Date: 1999/03/05
Raw View
"J.Barfurth" <techview@bfk-net.de> writes:

>Steve Clamage wrote<7bmhfj$s4h$1@engnews1.eng.sun.com>...
>>"Daniel Grob" <Daniel.Grob@elca.ch> writes:
>>
>>>If I write the following line of code:
>>
>>>IC_String *test = new IC_String(IC_String::fkt())

>>>In what sequence are the functions / operators called?

>>So we have this partial ordering:
>>    operator new before the constructor
>>    fkt before the constructor
>>    operator new before the assignment to test
>>Any ordering that satisfies those requirements is acceptable.

>Does this really mean there is no specified order 'constructor before the
>assignment to test' ?

>I always relied on code like
>    A* p = NULL;
>    try
>    {
>        p = new A();
>    }
>    catch (..) {}

>to leave p at NULL, if the ctor of a throws an exception.
>(The catch handlers will often be far away, and p might be a class member)

>Was I just LUCKY ??

That's an interesting question. I don't find anything in the
standard that says a value won't be assigned to p if the A
constructor exits via an exception.

It might be possible to read the definition of a new-expression
and the rules about sequence points so as to postpone the assignment
until after the constructor completes, but it doesn't seem that
way to me.

--
Steve Clamage, stephen.clamage@sun.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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/03/05
Raw View
In article <7bm890$hj0$1@news.eunet.ch>, Daniel Grob
<Daniel.Grob@elca.ch> writes
>
>Hello
>
>This might be a tricky question. I wonder, what you think about it...
>If I write the following line of code:
>
>IC_String *test = new IC_String(IC_String::fkt())
>
>where
>IC_String is a class
>new is the overloaded operator for the IC_String class

>fkt() is a simple function returning an long

A class static function?
#
>IC_String(long) is a contstructor for the IC_String class
>
>In what sequence are the functions / operators called?

You are getting confused between operator new (overloadable) and the new
operator.  The latter calls operator new (to allocate storage) and then
the ctor for the object to construct the object in the provide space.

At some time before the ctor is called the fkt() function must be
called.

>
>In my C++ book I see, that a constructor has precedence over the new
>operator. So the sequence should be:
>1. the function IC_String::fkt()
>2. the constructor IC_String()
>3. the new operator
>
>But what my compiler does is:
>1. the new operator
>2. the function IC_String::fkt()
>3. the constructor IC_String
>
>On another compiler the sequence is:
>1. the function IC_String::fkt()
>2. the new operator
>3. the constructor IC_String
>
>Now the question:
>Who is right? My C++ book? My compiler? The other compiler? Someone else?

See above, you are confused.  I believe that Both compilers are right.


Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Daniel Grob" <Daniel.Grob@elca.ch>
Date: 1999/03/05
Raw View
Steve Clamage wrote in message <7bmhfj$s4h$1@engnews1.eng.sun.com>...
>You are confusing precedence with order of operations.  Precedence
>determines only how operations are grouped.  It establishes a
>partial ordering, not necessarily a total ordering.
>
>Example:
>    f() + g() / h()
>Since / has higher precedence than +, the result of the division
>must be known before the addition can be performed. But the three
>functions can be called in any order. The only other requirements
>are that g and h must be called before the division can be performed,
>and f must be called before the addition can be performed.  Any
>ordering that meets those requirements is acceptable.

I don't agree with you! The precedence give an absolute ordering!
If I look again in my C++ book then I find:
Level 16L : () : function call
Level 16L : () : type construction
Level 15R : new, delete : free store management
Level 13L : *, /, % : multplicative operators
Level 12L : +, - : arithmetic operators
Level 2R : =, *=, /=, ... : assignment operators

Where higher levels are performed before lower levels and the letter behind
the number means that if there are more than one operator of the same level
from which side the calculation is started (R = from the right, L = from the
left).

So given your example (f() + g() / h()) there is only one allowed ordering:
1. f()
2. g()
3. h()
4. /
5. +

Given my example (IC_String *test = new IC_String(fkt())) there is also only
one allowed ordering:
1. fkt()
2. IC_String()
3. new
4. =

Am I missing something?


Regards Dany




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stephen.Clamage@Sun.COM (Steve Clamage)
Date: 1999/03/05
Raw View
"Daniel Grob" <Daniel.Grob@elca.ch> writes:


>Steve Clamage wrote in message <7bmhfj$s4h$1@engnews1.eng.sun.com>...
>>You are confusing precedence with order of operations.  Precedence
>>determines only how operations are grouped.  It establishes a
>>partial ordering, not necessarily a total ordering.
>>
>>Example:
>>    f() + g() / h()
>>Since / has higher precedence than +, the result of the division
>>must be known before the addition can be performed. But the three
>>functions can be called in any order. The only other requirements
>>are that g and h must be called before the division can be performed,
>>and f must be called before the addition can be performed.  Any
>>ordering that meets those requirements is acceptable.

>I don't agree with you! The precedence give an absolute ordering!
>If I look again in my C++ book then I find:
>Level 16L : () : function call
>Level 16L : () : type construction
>Level 15R : new, delete : free store management
>Level 13L : *, /, % : multplicative operators
>Level 12L : +, - : arithmetic operators
>Level 2R : =, *=, /=, ... : assignment operators

>Where higher levels are performed before lower levels ...
                         ^^^^^^^^^

You are still confusing precedence with order of operations. If
your book really uses the word "perform", it is incorrect. There
is not, and never has been in C or C++, such a rule on ordering.

The precedence rules specify ONLY how operations are grouped.
They allow you to eliminate some parentheses in expressions,
and that's about all. The grouping in turn implies a partial
ordering, as I explained above.

If you look in the C++ standard, you will find no precedence table
at all.  A footnote in section 5 explains that the precedence is
specified only indirectly via the syntax rules.

Precedence tables are found by some people to be a convenient
reference, but in fact the tables don't work right for all
expressions; the conditional operator ?: in particular needs to
occupy two different slots in a precedence table. Old-style
casts are also problematic, because the actual precedences form
a loop. Those two features are hard to describe in a table.

Finally, section 1.9 of the standard points out explicitly how
the order of operations can vary.

--
Steve Clamage, stephen.clamage@sun.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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Biju Thomas <bijuthom@ibm.net>
Date: 1999/03/05
Raw View
Steve Clamage wrote:
>
> "J.Barfurth" <techview@bfk-net.de> writes:
>
> >I always relied on code like
> >    A* p = NULL;
> >    try
> >    {
> >        p = new A();
> >    }
> >    catch (..) {}
>
> >to leave p at NULL, if the ctor of a throws an exception.
> >(The catch handlers will often be far away, and p might be a class member)
>
> That's an interesting question. I don't find anything in the
> standard that says a value won't be assigned to p if the A
> constructor exits via an exception.
>

The assignment operator causes the value of rhs to be assigned to the
lvalue at lhs. I believe this is the meaning of assignment operation in
C++.

The value to be assigned to 'p' is not constructed if the constructor
for 'A' exits via an exception. How can a value be assigned to 'p' if
the value doesn't exist?

--
Best regards,
Biju 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]