Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Today in my course

50 views
Skip to first unread message

Alf P. Steinbach

unread,
Feb 16, 2017, 8:03:36 PM2/16/17
to
On 17.02.2017 01:53, Stefan Ram wrote:
> In hour 6 of my course, I only have explained operators and
> function calls so far. I just have showed them
>
> main.cpp
>
> #include <iostream> // ::std::cout
> #include <ostream> // <<

James Kanze fixed that. No longer necessary to include `<iostream>` (for
this). Retroactively, this means that the examples in the C++03 standard
are no longer incorrect. :)


> #include <string> // "s
> #include <cstdlib> // ::std::rand

I'd rather include `<stdlib.h>`. Less trouble.


> using namespace ::std::literals;
>
> int main() { ::std::cout << ::std::rand() << "\n"s; }
>
> ::std::cout

Huh what's that?


> 41
>
> (We only edit what's between »<<« and »<<« in the last line
> and ignore the rest of the program in this part of the course.)
>
> A partecipant wanted to see the next random number,
> so he tried:
>
> main.cpp
>
> #include <iostream> // ::std::cout
> #include <ostream> // <<
> #include <string> // "s
> #include <cstdlib> // ::std::rand
>
> using namespace ::std::literals;
>
> int main() { ::std::cout << 0*::std::rand()+1*::std::rand() << "\n"s; }
>
> ::std::cout
>
> 18467

This different result is not guaranteed, because the order of evaluation
is unspecified.


> Good idea! What number do you expect the following program
> to print (we used a recent GCC, BTW)?
>
> main.cpp
>
> #include <iostream> // ::std::cout
> #include <ostream> // <<
> #include <string> // "s
> #include <cstdlib> // ::std::rand
>
> using namespace ::std::literals;
>
> int main() { ::std::cout << 1*::std::rand()+0*::std::rand() << "\n"s; }
>
> I was slightly surprised.
>
> (A good teaching example for the unspecified order of
> evaluation in C++, when an implementation is used that shows
> this »effect«!)

Oh, that's what you wanted to show.

Well.

Instead of the arithmetic hack the student could just use a
comma-expression. ;-)

The advanced student, still limited to edit the single expression, could
put a lambda there, and do just about anything.

I think C++ would have been better off with always well-defined and
predictable evaluation of expressions.


Cheers!,

- Alf

Alf P. Steinbach

unread,
Feb 16, 2017, 10:44:20 PM2/16/17
to
On 17.02.2017 02:34, Stefan Ram wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>>> #include <iostream> // ::std::cout
>>> #include <ostream> // <<
>> James Kanze fixed that. No longer necessary to include `<iostream>` (for
>> this). Retroactively, this means that the examples in the C++03 standard
>> are no longer incorrect. :)
>
> /That/ /was/ explain in the course.
>
> (I explained to the participants why »ostream« is /not/
> needed and then that it is /my personal preference/ to
> include it nonetheless.)

Yes, I meant `<ostream>`. Thanks.



>>> #include <string> // "s
>>> #include <cstdlib> // ::std::rand
>> I'd rather include `<stdlib.h>`. Less trouble.
>
> Why is it less trouble?

If you inadvertently forget to qualify something from the header and it
works with your compiler, then with `<stdlib.h>` the code will still
work with other compilers. See the recent thread about it, “Is std
library allowed to pollute the global namespace?”.

And unqualified names are less to both read and write.

Plus it's IMHO also good to be familiar with most all names from the C89
standard library, so that one can avoid using them as names of stuff one
defines.


Cheers!,

- Alf

David Brown

unread,
Feb 17, 2017, 3:17:45 AM2/17/17
to
On 17/02/17 02:02, Alf P. Steinbach wrote:

>
> I think C++ would have been better off with always well-defined and
> predictable evaluation of expressions.
>

Isn't that coming in C++17 ?

I think it is unnecessary to have a predictable evaluation order for
"f() + g()" - we've lived with that for decades. But people often
expect the evaluation order for "cout << f() << g();" to be defined, and
/that/ will be useful.



Juha Nieminen

unread,
Feb 17, 2017, 5:55:09 AM2/17/17
to
Stefan Ram <r...@zedat.fu-berlin.de> wrote:
> #include <iostream> // ::std::cout
> #include <ostream> // <<

"Let's include iostream, which includes both istream and ostream.
Let's then include ostream. Beacuse we like repetition so much.
And because we just love all those #include lines. We need more of them!"

And because reasons!

> #include <cstdlib> // ::std::rand

Isn't std::rand() deprecated or something? At least it should be.

Way to teach the use of functions they shouldn't be using.

> int main() { ::std::cout << ::std::rand() << "\n"s; }

Yeah, because that's so much more efficient than "\n".
And it adds so much to the code. (As in, nothing but potential
overhead. But who cares about that? The important thing is to
use fancy new C++ features! Except we are still using std::rand(),
because reasons!)

> int main() { ::std::cout << 0*::std::rand()+1*::std::rand() << "\n"s; }
>
> ::std::cout
>
> 18467
>
> Good idea!

I hope that was sarcasm.

Chris Vine

unread,
Feb 17, 2017, 6:23:26 AM2/17/17
to
On Fri, 17 Feb 2017 09:17:36 +0100
David Brown <david...@hesbynett.no> wrote:
> On 17/02/17 02:02, Alf P. Steinbach wrote:
>
> >
> > I think C++ would have been better off with always well-defined and
> > predictable evaluation of expressions.
> >
>
> Isn't that coming in C++17 ?

Probably.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0145r3.pdf

JiiPee

unread,
Feb 17, 2017, 6:26:21 AM2/17/17
to
On 17/02/2017 10:54, Juha Nieminen wrote:
> Stefan Ram <r...@zedat.fu-berlin.de> wrote:
>
>> #include <cstdlib> // ::std::rand
> Isn't std::rand() deprecated or something? At least it should be.
>
> Way to teach the use of functions they shouldn't be using.

I cannot see it being deprecated , but its not a good random function. I
guess you could teach it but needs to mention that this is not a good
one. I think rand() is ok for testing purposes because its much faster
to code. But not using in a serious application. I kind of wish std
would have a shortcut to rand() so we do not need to write those 6 lines
of code to get a simple random number.... I guess I could create my own
rand_ex? Thats a good idea by the way :). I recommend people to have
their "c_tools.h" file to add in all projects and then create maybe
rand_ex() to do it in c++11 way.

Chris Vine

unread,
Feb 17, 2017, 6:49:47 AM2/17/17
to
However, on looking at the latest available print of the standard
(n4640), large parts of the proposal on the order of evaluation of
expressions and function arguments have been rejected.

Manfred

unread,
Feb 17, 2017, 12:31:12 PM2/17/17
to
On 2/17/2017 2:34 AM, Stefan Ram wrote:
>> Instead of the arithmetic hack the student could just use a
>> comma-expression. ;-)
> I have already did one exercise today to prepare the mind
> for the comma expression, but I will not really introduce it
> in this course due to lack of time.
FWIW, /if/ the topic of order of evaluation is understood, then the
comma operator is pretty simple to understand too.
OTOH, the comma operator is pretty unique in its function.

Juha Nieminen

unread,
Feb 17, 2017, 2:29:33 PM2/17/17
to
JiiPee <n...@notvalid.com> wrote:
> I kind of wish std
> would have a shortcut to rand() so we do not need to write those 6 lines
> of code to get a simple random number....

Where are you getting that figure from? You can get a C++11 rng for
example like:

auto rng = std::bind(std::uniform_int_distribution<int>(1, 6), std::mt19937());
std::cout << rng() << "\n";

Vir Campestris

unread,
Feb 17, 2017, 4:55:54 PM2/17/17
to
On 17/02/2017 11:49, Chris Vine wrote:
> However, on looking at the latest available print of the standard
> (n4640), large parts of the proposal on the order of evaluation of
> expressions and function arguments have been rejected.

Good.

I can imagine a future where the two functions might be run in parallel
on different CPUs. Currently the overhead of setting such a thing up is
too much, so any parallelism is explicit (threads, or OpenCL).

Andy

Alf P. Steinbach

unread,
Feb 17, 2017, 9:55:44 PM2/17/17
to
I support explicit notation for where one wants or wants to permit
parallelism.

The consequences could be quite serious if the calls in

cout << a() << " " << b() << "\n";

were executed in parallel, without `a` and `b` being designed for
parallelism, e.g. trying to update the same variable.

Explicit is good, implicit is bad. In general. ;-)

In C++98 and C++03 the non-normative examples at the start of section 5,
like

i = v[i++]; // the behavior is unspecified

… directly contradicted the normative text right above,

“Between the previous and next sequence point a scalar object shall
have its stored value modified at most once by the evaluation of an
expression.”

… which dictates undefined behavior.

I think that these examples signal an original intent different from the
normative text's wording. Just like all the C++98/C++03 examples using
`<iostream>` output and failing to include also `<ostream>`, probably
signal an original intent that `operator<<` should be provided also via
the `<iostream>` header. It is now, as of C++11 and later.

So, is the presumed original intent of /unspecified/ behavior
incompatible with your envisioned possible parallelism?


Cheers!,

- Alf

Vir Campestris

unread,
Feb 18, 2017, 4:47:56 PM2/18/17
to
On 18/02/2017 02:54, Alf P. Steinbach wrote:
>
> I support explicit notation for where one wants or wants to permit
> parallelism.
>
> The consequences could be quite serious if the calls in
>
> cout << a() << " " << b() << "\n";
>
> were executed in parallel, without `a` and `b` being designed for
> parallelism, e.g. trying to update the same variable.
>
> Explicit is good, implicit is bad. In general. ;-)

We have exactly the same problem with a call like
x(a(), b()) - the order of evaluation there is undefined. Every system
I've ever used does it one way. Or the other. But never both. Why should
the order of evaluation in the explicit calls in your example be
defined? (The effects of reordering the operator<< calls would however
be bad)
>
> In C++98 and C++03 the non-normative examples at the start of section 5,
> like
>
> i = v[i++]; // the behavior is unspecified
>
> … directly contradicted the normative text right above,
>
> “Between the previous and next sequence point a scalar object shall
> have its stored value modified at most once by the evaluation of an
> expression.”
>
> … which dictates undefined behavior.
>
> I think that these examples signal an original intent different from the
> normative text's wording. Just like all the C++98/C++03 examples using
> `<iostream>` output and failing to include also `<ostream>`, probably
> signal an original intent that `operator<<` should be provided also via
> the `<iostream>` header. It is now, as of C++11 and later.
>
> So, is the presumed original intent of /unspecified/ behavior
> incompatible with your envisioned possible parallelism?

in i = v[i++] we have two things going on - the assign and the
increment. I see no reason why the language should define which happens
first.

I'd like a compiler that would tell me not to be so silly.

Andy
--
I'm doing too much C these days :(

Öö Tiib

unread,
Feb 18, 2017, 7:41:01 PM2/18/17
to
On Saturday, 18 February 2017 23:47:56 UTC+2, Vir Campestris wrote:
> On 18/02/2017 02:54, Alf P. Steinbach wrote:
> >
> > I support explicit notation for where one wants or wants to permit
> > parallelism.
> >
> > The consequences could be quite serious if the calls in
> >
> > cout << a() << " " << b() << "\n";
> >
> > were executed in parallel, without `a` and `b` being designed for
> > parallelism, e.g. trying to update the same variable.
> >
> > Explicit is good, implicit is bad. In general. ;-)
>
> We have exactly the same problem with a call like
> x(a(), b()) - the order of evaluation there is undefined. Every system
> I've ever used does it one way. Or the other. But never both. Why should
> the order of evaluation in the explicit calls in your example be
> defined? (The effects of reordering the operator<< calls would however
> be bad)

I have always thought that it is waste of time that such surprising
lack of order of evaluation was taken from C into C++. It causes
illusions, no tool warns of those and also it is really tiresome to
explain that every time to novices that there is such a yet another
bear trap. Why it is there? What are the benefits? None. Those bear
traps took years to learn. Waste of time.

> >
> > In C++98 and C++03 the non-normative examples at the start of section 5,
> > like
> >
> > i = v[i++]; // the behavior is unspecified
> >
> > … directly contradicted the normative text right above,
> >
> > “Between the previous and next sequence point a scalar object shall
> > have its stored value modified at most once by the evaluation of an
> > expression.”
> >
> > … which dictates undefined behavior.
> >
> > I think that these examples signal an original intent different from the
> > normative text's wording. Just like all the C++98/C++03 examples using
> > `<iostream>` output and failing to include also `<ostream>`, probably
> > signal an original intent that `operator<<` should be provided also via
> > the `<iostream>` header. It is now, as of C++11 and later.
> >
> > So, is the presumed original intent of /unspecified/ behavior
> > incompatible with your envisioned possible parallelism?
>
> in i = v[i++] we have two things going on - the assign and the
> increment. I see no reason why the language should define which happens
> first.

Why it should not? If to rewrite above not using the confusing punctuation
marks but method call syntax then it would be something like that:

i.assign(v.subscript(i.postIncrement());

Here is clear that i.postIncrement has to be called before v.subscript
can be called because v.subscript uses whatever i.postIncrement returns
as its argument. Also v.subscript has to be called before i.assign can
be called for exactly same reason.

0 new messages