5

For this non-variadic example:

int     Func1();
double  Func2();
void    MyFunc( int, double );

int  main()
{
    MyFunc( Func1(), Func2() );
    //...
}

it's not specified whether Func1() or Func2() is computed first, just that both must be done before MyFunc() is called.

How does this sequencing work with the expansion of variadic arguments?

template < typename Func, typename ...Args >
void  MyFunc2( Func &&f, Args&& ...a )
{
    int  b[] = { f( std::forward<Args>(a) )... };
    //...
}

Let's say that f is a function object that changes its state after its first call. Will f be called in order for each segment of a? In other words, will f be called on the first item in a's list, then the second item, the third, etc., instead of randomly skipping through the expanded list? Is there what we used to call sequence points between each item?

Griwes
  • 8,805
  • 2
  • 43
  • 70
CTMacUser
  • 1,996
  • 1
  • 16
  • 27
  • What does "what we used to call sequence points" mean? – Johannes Schaub - litb May 26 '12 at 10:06
  • I only know a little bit about it, but statements like "there's a sequence point between *x* and *y*" have been replaced with "*x* is sequenced before *y*." The new full definition is more precise and includes accommodations for threading. – CTMacUser May 26 '12 at 22:05

1 Answers1

5

Yes, brace enclosed initializer lists guarantee an evaluation order of left-to-right, while function calls do not. So MyFunc2 will sequence correctly.

The Wikipedia article covers this: https://en.wikipedia.org/wiki/Variadic_templates

Is there what we used to call sequence points between each item?

No, while it uses a comma token it is not the comma operator.

Pubby
  • 51,882
  • 13
  • 139
  • 180
  • Interesting. However, the example with `pass` doesn't work with GCC-4.7. The expressions in `pass{std::cout << args...}` are executed right-to-left on my machine. Is this a bug in GCC-4.7? Or is the description on Wikipedia wrong? – nosid May 26 '12 at 09:20
  • @nosid I think I recall hearing that GCC had that bug. litb wrote that article segment and he's never wrong (hehe, I'll ask him next time he comes online) – Pubby May 26 '12 at 09:53
  • You are right. I have found it in §8.5.4.4 (draft n3290): "[..] The initializer clauses [..] are evaluated in the order in which they appear." and "This evaluation ordering holds [..] - even though ordinarily there are no sequencing constraints on the arguments of a call." – nosid May 26 '12 at 10:37
  • I already knew that the separators are not the comma-operator from [another question of mine](http://stackoverflow.com/a/10226717/1010226), answered by @nosid. – CTMacUser May 26 '12 at 22:10
  • Although my second example used variadic expansion for initialization, I wanted to know if expansion is sequenced under all circumstances. Looking around, the answer here is right that it's not. The section on variadic templates (14.5.3) gives no sequencing directions and states the expansion acts exactly as a regular comma-separated list in the same place. So the sequencing rules match whatever a normal list would have there. (Braced-initialization lists are sequenced in 8.5.4/p4, function arguments are unsequenced in 8.3.6/p9.) – CTMacUser May 26 '12 at 22:22