Yes, the order of the evaluation of initializer-clauses is guaranteed in braced-init-list.
From the standard, §11.6.4/4 List-initialization [dcl.init.list]:
(emphasis mine)
Within the initializer-list of a braced-init-list, the
initializer-clauses, including any that result from pack expansions,
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 ]
From cppreference.com:
Every initializer clause is sequenced
before any
initializer clause that follows it in the braced-init-list. This is in
contrast with the arguments of a function call
expression,
which are
unsequenced.
Example for the note of the standard,
struct A { A(int, int) {} };
...
int i = 0;
A a1(i++, i++); // used as the arguments of the constructor; unsequenced
A a2{i++, i++}; // used as the arguments of the constructor; sequenced, within the initializer-list of a braced-init-list
note
section i.e. the constructor call part. – Myongmyopia