3

As I understand it, given the following code:

template<int N> 
int i = i<N - 1> + i<N - 1>;  // primary variable template

template<> int i<0> = 1;      // and explicit specialization

the following program must return 2:

int main () { return i<1>; }

but this program can return 0 or 4:

int main () { return i<2>; }

since evaluating the instantiation of i<2> gives:

int i<2> = i<1> + i<1>;       // generated by the compiler

Here, since i<1> is only implicitly instantiated, the compiler can use either the statically initialized value of i<1>, which is 0, or the dynamically initialized value, which is 2.

Here's a comparison of different compilers giving different outputs (clang returns 0, gcc returns 4).

The question is - can this program return 2?

int main () { return i<2>; }

i.e. in the initialization of i<2>, can different initializations be used for the different uses of i<1>? Can the program return some other value entirely?

cigien
  • 57,834
  • 11
  • 73
  • 112
  • 1
    "*the statically initialized value of `i<1>`, which is 0*" - where do you get 0 from? You yourself said just above that statement that `i<1>` must be 2 instead. – Remy Lebeau Jun 07 '20 at 03:33
  • @RemyLebeau From [here](https://eel.is/c++draft/basic.start.static#3). Also, in the first example, `i<1>` must be dynamically initialized, since it is used. But in the second program `i<1>` is not explicitly used, so the statically initialized version could be used. Edited the question a bit, hope that helps. – cigien Jun 07 '20 at 03:37
  • I don't see anything in this code that would cause zero initialization as described in that article – Remy Lebeau Jun 07 '20 at 03:44
  • @RemyLebeau Fair enough. I'm not saying my interpretation is definitely right. What about the clang output in the link? Do you think that's a bug then? – cigien Jun 07 '20 at 03:46
  • I don't know, because I can't see the output on that link right now. I'm on a phone right now, and that site is horrible for mobile – Remy Lebeau Jun 07 '20 at 03:47
  • @RemyLebeau aah, no worries. clang prints 0. I can believe that's a bug, but then I'd like a language lawyer explanation of why clang must output 4, as you say it should. – cigien Jun 07 '20 at 03:49

2 Answers2

2

You know from Recursive computation using variable templates - gcc vs clang that the dynamic initializations of i<1> and i<2> are indeterminately sequenced. Indeterminately sequenced evaluations can't interleave (overlap):

Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [ Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first.  — end note ]

So in the dynamic initialization of int i<2> = i<1> + i<1>;, either the static or the dynamic value of i<1> is used for both summands, depending on whether the dynamic initialization of i<1> has already happened.

Language Lawyer
  • 3,378
  • 1
  • 12
  • 29
-2

the statically initialized value of i<1>, which is 0

Where do you get 0 from? You yourself said just above that statement that i<1> must be 2.

So, given:
i<0> = 1
And:
i<1> = i<0> + i<0> = 1 + 1 = 2
And:
i<2> = i<1> + i<1>
Then:
i<2> = 2 + 2 = 4

It can't be anything other than 4.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770