According to the n4296 C++ standard document:
[dcl.init.list] (8.5.4.4) (pg223-224)
Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list. [Note: This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call. —end note ]
(emphasis mine)
The note was added here: http://ift.tt/1rdFxtu
This reads to me that the following code:
#include <iostream>
struct MyType {
MyType(int i, int j, int k, int l)
: sum(i + j + k + l)
{
}
int sum;
};
int main()
{
int i = 0;
std::cout << MyType{ ++i, ++i, ++i, ++i }.sum << '\n';
}
Should print "10".
This is my reasoning:
- MyType is being initialized via a braced-init-list
- braced-init-lists are evaluated in order
- even when it is interpreted as arguments of a constructor call
- this means that it should be evaluated as MyType(1,2,3,4)
That is to say, the above code should behave exactly like this code:
#include <initializer_list>
#include <iostream>
int main()
{
int i = 0;
std::initializer_list<int> il{++i, ++i, ++i, ++i};
std::cout << *il.begin() + *(il.begin() + 1) + *(il.begin() + 2) + *(il.begin() + 3) << '\n';
}
But it does not. The first example prints '16' and the second example prints '10'
Literally every compiler from every vendor that I can get my hands on prints '16', seemingly ignoring that part of the standard and not inserting sequence points.
What am I missing here?
Note: The following seem to be related to this question:
Aucun commentaire:
Enregistrer un commentaire