Topic: Evaluation order of init list elements
Author: James Kanze <james.kanze@gmail.com>
Date: Sun, 7 Feb 2010 18:54:01 CST Raw View
On Feb 5, 12:42 am, Scott Meyers <NeverR...@aristeia.com> wrote:
> Given
> int f1();
> int f2();
> int vals[2] = { f1(), f2() };
> 8.5.1/2 tells me that vals[0] is copy-initialized from the
> result of calling f1 and vals[1] is copy initialized from the
> result of calling f2. But am I guaranteed that f1 is called
> before f2? Would the following generated code be valid?
> int temp1 = f2();
> int temp2 = f1();
> vals[0] = temp1;
> vals[1] = temp2;
> Personally, I hope not, but I can't find anything guaranteeing
> evaluation order of elements of initializer lists.
Each of "f1()" and "f2()" are full expressions (according to
1.6/12); the notes in the following sections make it clear that
the initialization of the variable itself is intended to be part
of the full expression. So there is a sequence point between
each initialization. On the other hand, I can't find anything
off hand which would forbid the equivalent of:
vals[1] = f2();
vals[0] = f1();
This would seem to be an oversight, however.
> A similar question arises in the initialization of elements of
> std::initializer_list objects:
> struct HiMom {
> HiMom(std::initializer_list<int> il);
> };
> HiMom m { f1(), f2() };
> Does the standard say anything about the evaluation order of
> the calls to f1 and f2?
Wouldn't this be covered by 12.4/3: "There is a sequence point
(1.9) after the initialization of each base and member."?
--
James Kanze
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Scott Meyers <NeverRead@aristeia.com>
Date: Mon, 8 Feb 2010 11:37:43 CST Raw View
James Kanze wrote:
> Each of "f1()" and "f2()" are full expressions (according to
> 1.6/12); the notes in the following sections make it clear that
> the initialization of the variable itself is intended to be part
> of the full expression. So there is a sequence point between
> each initialization.
I should have been clearer that I'm interested in the situation in C++0x, not
C++03. Note that in draft C++0x, the term "sequence point" does not exist.
(There are still sequencing constraints, but they are not specified using the
language of C++03.)
Also, section 1.6 of C++03 is "Syntax notation" and has only two paragraphs.
Are you sure that is the section you meant to refer to?
Scott
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Mon, 8 Feb 2010 11:39:11 CST Raw View
James Kanze wrote:
> On Feb 5, 12:42 am, Scott Meyers <NeverR...@aristeia.com> wrote:
>> Given
>
>> int f1();
>> int f2();
>
>> int vals[2] = { f1(), f2() };
>
>> 8.5.1/2 tells me that vals[0] is copy-initialized from the
>> result of calling f1 and vals[1] is copy initialized from the
>> result of calling f2. But am I guaranteed that f1 is called
>> before f2? Would the following generated code be valid?
>
>> int temp1 = f2();
>> int temp2 = f1();
>> vals[0] = temp1;
>> vals[1] = temp2;
>
>> Personally, I hope not, but I can't find anything guaranteeing
>> evaluation order of elements of initializer lists.
>
> Each of "f1()" and "f2()" are full expressions (according to
> 1.6/12); the notes in the following sections make it clear that
> the initialization of the variable itself is intended to be part
> of the full expression. So there is a sequence point between
> each initialization.
>
I think it can occur like this: A valid way to evaluate the full-expressions
in an aggregate braced list is to stick all evaluations between the same
sequence points. That way, we still have a sequence point after each
evaluation of full-expressions, yet we have no sequence point *between*
them. The critical part is that the order of evaluation is not specified, i
think.
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: James Kanze <james.kanze@gmail.com>
Date: Mon, 8 Feb 2010 22:29:27 CST Raw View
On Feb 8, 5:37 pm, Scott Meyers <NeverR...@aristeia.com> wrote:
> James Kanze wrote:
> > Each of "f1()" and "f2()" are full expressions (according to
> > 1.6/12); the notes in the following sections make it clear
> > that the initialization of the variable itself is intended
> > to be part of the full expression. So there is a sequence
> > point between each initialization.
> I should have been clearer that I'm interested in the
> situation in C++0x, not C++03. Note that in draft C++0x, the
> term "sequence point" does not exist. (There are still
> sequencing constraints, but they are not specified using the
> language of C++03.)
I know that the language concerning ordering has been completely
reworked, in order to take threads into account. I believe,
however, that the intent was that anything that was guaranteed
before is still guaranteed, and that if this isn't the case, it
would be considered a defect in the current draft.
> Also, section 1.6 of C++03 is "Syntax notation" and has only
> two paragraphs. Are you sure that is the section you meant to
> refer to?
I don't have my copy on line here to verify, so I can't exclude
a mistyping of one sort or the other. (Nor can I verify which
section I actually meant.)
--
James Kanze
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Jonathan Mcdougall <jonathanmcdougall@gmail.com>
Date: Mon, 8 Feb 2010 22:26:28 CST Raw View
> > Each of "f1()" and "f2()" are full expressions (according to
> > 1.6/12); the notes in the following sections make it clear that
> > the initialization of the variable itself is intended to be part
> > of the full expression. So there is a sequence point between
> > each initialization.
>
> I should have been clearer that I'm interested in the situation in
> C++0x, not C++03. Note that in draft C++0x, the term "sequence point"
> does not exist.
C++03 says (1.9/13) "certain contexts in C++ cause the evaluation of a
full-expression that results from a syntactic construct other than
_expression_" and then proceeds with =x becoming (x) at
initialization.
This could be interpreted as saying that initializer lists are
rewritten
so that the initialization of each element is a full-expression and
that
therefore there is a sequence point between each initialization. This
seems to be James' interpretation. It is not so clear to me, but it
doesn't matter.
However, I am not seeing this language in the 2009-11-09 draft
anymore.
It seems to have been replaced with 1.9/10: "If a language construct
is defined to produce an implicit call of a function, a use of the
language construct is considered to be an expression for the purposes
of
this definition", which sounds a lot stricter than in C++03. However,
if we consider "int a=2" as being a function call of int::int(), then
it might be possible to interpret this so that
int a[] = {15, 16};
actually means
int a[2];
a[0]::int(15);
a[1]::int(16);
or
int a[2];
a[1]::int(16);
a[0]::int(15);
Finally, in C++0x, 8.5.1/17 says "The full-expressions in an
initializer-clause are evaluated in the order in which they appear".
Therefore, we could say that it is guaranteed that with
int vals[2] = { f1(), f2() };
each element is initialized in increasing order from its corresponding
initializer-clause and that there is a sequence point after each (or,
in
C++0x parlance, that the initialization of one element is sequenced
before the initialization of the next one).
Concerning std::initializer_list, 8.5.4/4 says that the implementation
behaves as if "each element of [an internally allocated array] is
copy-initialized with the corresponding element of the initializer
list". I think it follows that all that applies to aggregates also
applies to std::initializer_list.
--
Jonathan Mcdougall
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Scott Meyers <NeverRead@aristeia.com>
Date: Tue, 9 Feb 2010 01:05:21 CST Raw View
Jonathan Mcdougall wrote:
>
> Finally, in C++0x, 8.5.1/17 says "The full-expressions in an
> initializer-clause are evaluated in the order in which they appear".
As I pointed out in a separate post, the problem is that this seems to
apply only *within* each element of an initializer list if the "=" is
omitted in the initialization. That is, in
int vals[] = { f1(), f2() };
the grammar makes the entire initialization list an initializer
clause, and I agree that f1() must be called before f2(), but in
int vals[] { f1(), f2() };
the entire initialization list is no longer an initializer clause.
Rather, each element of the initialization list is its own initializer
clause.
I'm tempted to suggest that it should be a defect if the two
constructs above have different semantics, but, alas, the ground for
this kind of thing has long been broken: copy and direct
initialization are syntactially nearly identical, but they have
different semantics.
> Concerning std::initializer_list, 8.5.4/4 says that the implementation
> behaves as if "each element of [an internally allocated array] is
> copy-initialized with the corresponding element of the initializer
> list". I think it follows that all that applies to aggregates also
> applies to std::initializer_list.
Yes, I agree, thanks for pointing this out.
Scott
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Jonathan Mcdougall <jonathanmcdougall@gmail.com>
Date: Tue, 9 Feb 2010 10:55:57 CST Raw View
> That is, in
>
> int vals[] = { f1(), f2() };
>
> the grammar makes the entire initialization list an initializer
> clause[..] but in
>
> int vals[] { f1(), f2() };
>
> the entire initialization list is no longer an initializer clause.
> Rather, each element of the initialization list is its own
> initializer clause.
I see what you're saying now:
initializer:
brace-or-equal-initializer
( expression-list )
brace-or-equal-initializer:
= initializer-clause
braced-init-list
initializer-clause:
assignment-expression
braced-init-list
initializer-list:
initializer-clause ...opt
initializer-list , initializer-clause ...opt
braced-init-list:
{ initializer-list ,opt }
{ }
With this, these
int a[] = {1, 2, 3};
int b[] {4, 5, 6};
become
int a[] = initializer-clause
int b[] braced-init-list
which in turn gives
int a[] = initializer-clause{ braced-init-list{ initializer-list{
initializer-clause{ assignment-expression },
initializer-clause{ assignment-expression },
initializer-clause{ assignment-expression } } } }
int b[] braced-init-list{ initializer-list{
initializer-clause{ assignment-expression },
initializer-clause{ assignment-expression },
initializer-clause{ assignment-expression } } }
Because 8.5.1/17 talks about initializer clauses, the sequencing of
b[] does not seem to be specified for the moment. Whether this is
intentional or not is not clear to me, but I'd say /17 is a typo:
it should read "The full-expressions in an *initializer-list* are
evaluated in the order in which they appear."
--
Jonathan Mcdougall
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Wed, 10 Feb 2010 11:51:59 CST Raw View
Jonathan Mcdougall wrote:
>> That is, in
>>
>> int vals[] = { f1(), f2() };
>>
>> the grammar makes the entire initialization list an initializer
>> clause[..] but in
>>
>> int vals[] { f1(), f2() };
>>
>> the entire initialization list is no longer an initializer clause.
>> Rather, each element of the initialization list is its own
>> initializer clause.
>
> I see what you're saying now:
>
> [ snipped ]
>
> Because 8.5.1/17 talks about initializer clauses, the sequencing of
> b[] does not seem to be specified for the moment. Whether this is
> intentional or not is not clear to me, but I'd say /17 is a typo:
> it should read "The full-expressions in an *initializer-list* are
> evaluated in the order in which they appear."
>
Saying that the full-expressions in an initializer-list are evaulated in
order would wrongly sequence function argument lists.
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Wed, 10 Feb 2010 11:51:30 CST Raw View
Jonathan Mcdougall wrote:
>> That is, in
>>
>> int vals[] = { f1(), f2() };
>>
>> the grammar makes the entire initialization list an initializer
>> clause[..] but in
>>
>> int vals[] { f1(), f2() };
>>
>> the entire initialization list is no longer an initializer clause.
>> Rather, each element of the initialization list is its own
>> initializer clause.
>
> I see what you're saying now:
>
> initializer:
> brace-or-equal-initializer
> ( expression-list )
>
> brace-or-equal-initializer:
> = initializer-clause
> braced-init-list
>
> initializer-clause:
> assignment-expression
> braced-init-list
>
> initializer-list:
> initializer-clause ...opt
> initializer-list , initializer-clause ...opt
>
> braced-init-list:
> { initializer-list ,opt }
> { }
>
> With this, these
>
> int a[] = {1, 2, 3};
> int b[] {4, 5, 6};
>
> become
>
> int a[] = initializer-clause
> int b[] braced-init-list
>
> which in turn gives
>
> int a[] = initializer-clause{ braced-init-list{ initializer-list{
> initializer-clause{ assignment-expression },
> initializer-clause{ assignment-expression },
> initializer-clause{ assignment-expression } } } }
>
> int b[] braced-init-list{ initializer-list{
> initializer-clause{ assignment-expression },
> initializer-clause{ assignment-expression },
> initializer-clause{ assignment-expression } } }
>
> Because 8.5.1/17 talks about initializer clauses, the sequencing of
> b[] does not seem to be specified for the moment. Whether this is
> intentional or not is not clear to me, but I'd say /17 is a typo:
> it should read "The full-expressions in an *initializer-list* are
> evaluated in the order in which they appear."
>
As a braced-init-list "is-a" initializer-clause (because we can derive a
braced-init-list from an initializer-clause), statements about an
initializer-clause could also apply to braced-init-lists.
At least, that seems to be a common technique accross the Standard. I have
to say that this is counter intuitive to me. And I don't know whether this
is on purpose or not, tho.
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Scott Meyers <NeverRead@aristeia.com>
Date: Thu, 4 Feb 2010 18:42:50 CST Raw View
Given
int f1();
int f2();
int vals[2] = { f1(), f2() };
8.5.1/2 tells me that vals[0] is copy-initialized from the result of calling
f1 and vals[1] is copy initialized from the result of calling f2. But am I
guaranteed that f1 is called before f2? Would the following generated code
be valid?
int temp1 = f2();
int temp2 = f1();
vals[0] = temp1;
vals[1] = temp2;
Personally, I hope not, but I can't find anything guaranteeing evaluation
order of elements of initializer lists.
A similar question arises in the initialization of elements of
std::initializer_list objects:
struct HiMom {
HiMom(std::initializer_list<int> il);
};
HiMom m { f1(), f2() };
Does the standard say anything about the evaluation order of the calls to f1
and f2?
Thanks,
Scott
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Kaz Kylheku <kkylheku@gmail.com>
Date: Fri, 5 Feb 2010 13:18:49 CST Raw View
On 2010-02-05, Scott Meyers <NeverRead@aristeia.com> wrote:
> Given
>
> int f1();
> int f2();
>
> int vals[2] = { f1(), f2() };
>
> 8.5.1/2 tells me that vals[0] is copy-initialized from the result of calling
> f1 and vals[1] is copy initialized from the result of calling f2. But am I
> guaranteed that f1 is called before f2?
I'm certain that in C this order is unspecified (by explicit wording).
Here it is, paragraph 23 of 6.7.8 Initialization:
The order in which any side effects occur among the initialization list
expressions is unspecified. (Footnote: In particular, the evaluation order
need not be the same as the order of subobject initialization.)
In the C++ standard, I cannot find such explicit wording.
3.6.2 has a [Note: ...] which claims that ``8.5.1 describes the order in which
aggregate members are initialized.''.
But 8.5.1 neglects to specify such a thing. In fact the word ``order''
only appears in 8.5.1 once, where it used to specify that the initializer
clauses are written in increasing subscript and member order.
Oops. Unspecified by the omission of a requirement?
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Fri, 5 Feb 2010 13:24:34 CST Raw View
Scott Meyers wrote:
> Given
>
> int f1();
> int f2();
>
> int vals[2] = { f1(), f2() };
>
> 8.5.1/2 tells me that vals[0] is copy-initialized from the result of
> calling
> f1 and vals[1] is copy initialized from the result of calling f2. But am
> I
> guaranteed that f1 is called before f2? Would the following generated
> code be valid?
>
> int temp1 = f2();
> int temp2 = f1();
> vals[0] = temp1;
> vals[1] = temp2;
>
> Personally, I hope not, but I can't find anything guaranteeing evaluation
> order of elements of initializer lists.
>
The expressions in the aggregate initializer are full-expressions, and their
evaluation order is given in 8.5.1/17
> A similar question arises in the initialization of elements of
> std::initializer_list objects:
>
> struct HiMom {
> HiMom(std::initializer_list<int> il);
> };
>
> HiMom m { f1(), f2() };
>
> Does the standard say anything about the evaluation order of the calls to
> f1 and f2?
>
This seems to be covered by 8.5.1/17 likewise.
However, i'm unsure whether it applies if the parse tree does not contain an
"initializer-clause" containing all the expressions. It goes the
"initializer -> brace-or-equal-initializer -> braced-init-list -> {
initializer-list } -> { initializer-list, initializer-clause } -> {
initializer-clause, initializer-clause } -> { assignment-expression,
assignment-expression }" way.
However, the tree contains a "braced-init-list", which is one left side of
"initializer-clause". I'm unsure tho whether this means that the statement
in 8.5.1/17 applies to the shown code likewise. This is the case tho also
for other parts of the Standard (especially with statements about
"qualified-id" applying to cases where no qualified-id appears in the parse
tree, like for the tree of a using-declaration).
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Kaz Kylheku <kkylheku@gmail.com>
Date: Sat, 6 Feb 2010 09:44:31 CST Raw View
On 2010-02-05, Johannes Schaub (litb) <schaub-johannes@web.de> wrote:
> Scott Meyers wrote:
>> Personally, I hope not, but I can't find anything guaranteeing evaluation
>> order of elements of initializer lists.
>>
> The expressions in the aggregate initializer are full-expressions, and their
> evaluation order is given in 8.5.1/17
My copy of 14882:2003 doesn't have a pararaph 17; 8.5.1 goes to 15.
Draft feature?
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Jonathan Mcdougall <jonathanmcdougall@gmail.com>
Date: Sat, 6 Feb 2010 09:43:38 CST Raw View
> int f1();
> int f2();
> int vals[2] = { f1(), f2() };
>
> 8.5.1/2 tells me that vals[0] is copy-initialized from the result of
> calling f1 and vals[1] is copy initialized from the result of calling
> f2. But am I guaranteed that f1 is called before f2?
There is no sequence point between f1() and f2(); therefore whether
f1() is executed before f2() is unspecified.
> Would the following generated code be valid?
>
> int temp1 = f2();
> int temp2 = f1();
> vals[0] = temp1;
> vals[1] = temp2;
>
> Personally, I hope not, but I can't find anything guaranteeing
> evaluation order of elements of initializer lists.
Unless I'm missing something, it seems to me you are confusing the
order of evaluation of arguments with their actual usage. With
f(a(), b());
it is unspecified whether a() is executed before b(), but it is
guaranteed that the return value of a() is the first argument. The
same applies to initializer lists. Although C++2003 is not crystal
clear for arrays, C99 is quite to the point (6.7.8/17).
--
Jonathan Mcdougall
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Scott Meyers <NeverRead@aristeia.com>
Date: Sat, 6 Feb 2010 12:04:16 CST Raw View
Johannes Schaub (litb) wrote:
> The expressions in the aggregate initializer are full-expressions, and their
> evaluation order is given in 8.5.1/17
Are you sure? 8.5.1/17 says
The full-expressions in an initializer-clause are evaluated in the
order in which they appear.
But given a braced-init-list, each *element* of the list is an
initializer-clause, so given
{ IC1, IC2, ... , ICn }
my reading of 8.5.1/17 is that *within* each IC (i.e., within each
initializer-clause), full expressions are evaluated left to right, but I don't
see how 8.5.1/17 says anything about the relative evaluation order of adjacent
initializer-clauses, e.g., IC1 and IC2.
I hope I'm missing something.
Scott
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Scott Meyers <NeverRead@aristeia.com>
Date: Sat, 6 Feb 2010 12:03:20 CST Raw View
Kaz Kylheku wrote:
> 3.6.2 has a [Note: ...] which claims that ``8.5.1 describes the order in which
> aggregate members are initialized.''.
>
> But 8.5.1 neglects to specify such a thing.
Actually, 8.5.1 does specify the order in which aggregate members are
initialized, but that's not the question. The question is the order in which
the initialization expressions are evaluated. Intuitively, they'd be the same
thing, but it's not uncommon for standards to sometimes be counterintuitive.
Scott
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Kaz Kylheku <kkylheku@gmail.com>
Date: Sat, 6 Feb 2010 12:03:51 CST Raw View
On 2010-02-05, Scott Meyers <NeverRead@aristeia.com> wrote:
> Given
>
> int f1();
> int f2();
>
> int vals[2] = { f1(), f2() };
>
> 8.5.1/2 tells me that vals[0] is copy-initialized from the result of calling
> f1 and vals[1] is copy initialized from the result of calling f2. But am I
> guaranteed that f1 is called before f2? Would the following generated code
> be valid?
>
> int temp1 = f2();
> int temp2 = f1();
> vals[0] = temp1;
> vals[1] = temp2;
>
> Personally, I hope not
Your hope seems misplaced given that the language has unspecified evaluation
order (inherited from C) in more significant places, such as function calls,
and subexpressions of most operators.
Given f3(f1(), f2()); or f1() + f2() you don't know in what order f1 and
f2 are called.
This is a gaping lack of rigor that needs to be fixed in C and C++.
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Sun, 7 Feb 2010 18:43:27 CST Raw View
Scott Meyers wrote:
> Johannes Schaub (litb) wrote:
>> The expressions in the aggregate initializer are full-expressions, and
>> their evaluation order is given in 8.5.1/17
>
> Are you sure? 8.5.1/17 says
>
> The full-expressions in an initializer-clause are evaluated in the
> order in which they appear.
>
> But given a braced-init-list, each *element* of the list is an
> initializer-clause, so given
>
> { IC1, IC2, ... , ICn }
>
> my reading of 8.5.1/17 is that *within* each IC (i.e., within each
> initializer-clause), full expressions are evaluated left to right, but I
> don't see how 8.5.1/17 says anything about the relative evaluation order
> of adjacent initializer-clauses, e.g., IC1 and IC2.
>
> I hope I'm missing something.
>
I've described exactly that concern at the end of my answer. But i don't
share your worrying with the array case. The initializer there looks like "=
{ .... }", and the "{ ... }" part is an initializer-clause, thus containing
all the full-expressions in question.
My concern is about the initializer looking like "{ ... }" (your second
question), and in *that* case, what you say applies: *within* each IC, we
have initializer-clauses.
That is what my talking was about at the end of my answer.
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Scott Meyers <NeverRead@aristeia.com>
Date: Sun, 7 Feb 2010 18:44:21 CST Raw View
Jonathan Mcdougall wrote:
>>
>> int f1();
>> int f2();
>> int vals[2] = { f1(), f2() };
>>
>> 8.5.1/2 tells me that vals[0] is copy-initialized from the result of
>> calling f1 and vals[1] is copy initialized from the result of calling
>> f2. But am I guaranteed that f1 is called before f2?
>
> There is no sequence point between f1() and f2(); therefore whether
> f1() is executed before f2() is unspecified.
That's the essence of the question: is it or is it not specified? I
should have been clearer in my post that I am interested in the answer
for C++0x, not C++03. The question is more important in C++0x,
because braced-init-lists may be used for virtually any kind of
initialization. In C++03, they may be used only to initialize
aggregates.
> Unless I'm missing something, it seems to me you are confusing the
> order of evaluation of arguments with their actual usage. With
>
> f(a(), b());
>
> it is unspecified whether a() is executed before b(), but it is
> guaranteed that the return value of a() is the first argument. The
> same applies to initializer lists. Although C++2003 is not crystal
> clear for arrays, C99 is quite to the point (6.7.8/17).
But I don't see how C99 applies in this instance to C++0x, especially
in the second part of my question, which had to do with
braced-init-lists used to initialize std::initializer_list objects:
> struct HiMom {
> HiMom(std::initializer_list<int> il);
> };
>
> HiMom m { f1(), f2() };
>
> Does the standard say anything about the evaluation order of the calls to f1
> and f2?
Scott
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]