[class.base.init]
7 The expression-list or braced-init-list in a mem-initializer is
used to initialize the designated subobject (or, in the case of a
delegating constructor, the complete class object) according to the
initialization rules of [dcl.init] for direct-initialization.
[dcl.init]
19 If the initializer is a parenthesized expression-list, the
expressions are evaluated in the order specified for function calls.
Given the above two paragraph, I would conclude that the order of evaluation in...
A( CreateIntFromBuffer(aBuffer), CreateIntFromBuffer(aBuffer) )
... of the two calls is unspecified (other than not interleaving). So you cannot rely on the left call completing before the right call, or vice-versa.
One could force a left to right evaluation order by using a brace init list like...
A{ CreateIntFromBuffer(aBuffer), CreateIntFromBuffer(aBuffer) }
... but I would call it at least a somewhat arcane use of brace initialization. Consider refactoring.
In a pinch, one could use a named function that returns an A
, and delegate to the copy/move constructor:
struct A
{
static A makeA(std::vector<u8>::const_iterator& aBuffer) {
int a = CreateIntFromBuffer(aBuffer);
int b = CreateIntFromBuffer(aBuffer);
return A(a,b);
}
A( int a, int b ) : mA(a), mB(b) {}
A( std::vector<u8>::const_iterator& aBuffer ) : A(makeA(aBuffer)) {}
};
Thanks to guaranteed copy elision, this won't actually involve any copies.