title: Differences in constexpr evaluation in different compiler versions
body: <p>I have the following program:</p>
  
  <pre><code>constexpr int flag (int);
  
  template&lt;class Tag&gt;
  struct writer {
    friend constexpr int flag (Tag) {
      return 0;
    }
  };
  
  template&lt;bool B, class Tag = int&gt;
  struct dependent_writer : writer&lt;Tag&gt; { };
  
  template&lt;
    bool B = noexcept (flag (0)),
    int    =   sizeof (dependent_writer&lt;B&gt;)
  &gt;
  constexpr bool f () {
    return B;
  }
  
  int main () {
    constexpr bool a = f();
    constexpr bool b = f();
  
    static_assert( !a, "was not instantiated" );
    static_assert( !b, "was not instantiated" ); // here's the difference
  }
  </code></pre>
  
  <p>Interestingly, this program compiles with gcc 5.2 and clang 3.6 in C++11, C++14 and C++17 mode. However, with gcc 4.7, 4.8 and 4.9 the following error occurs:</p>
  
  <pre><code>main.cpp: In function 'int main()':
  main.cpp:26:7: error: static assertion failed: was not instantiated
         static_assert( !b, "was not instantiated" ); // here's the difference
         ^
  </code></pre>
  
  <p>It appears that in the old compilers, the default template parameters of the template function <code>f()</code> are decided upon at the function call site. The first time <code>f()</code> is called, the template class <code>writer&lt;int&gt;</code> gets instantiated finally, which defines the function external function <code>flag()</code>. This changes the value of <code>noexcept(flag(0))</code>, because the compiler can now tell by inspection, that this function is noexcept, since it finds a definition, the second time <code>f()</code> is called. Therefore, the found template arguments are different the second time <code>f()</code> is called. </p>
  
  <p>On the other hand, the newer compilers seem to decide on the default template parameters at the point the template function <code>f()</code> is declared and therefore the result is the same both times. </p>
  
  <p>This former behaviour (with gcc 4.7 to 4.9) appears a bit strange to me. I would like to know, if that behaviour was standard conforming anyways and if not, which part of the standard it is contradicting. </p>
  
  <p><strong>NOTE:</strong> The question <a href="https://stackoverflow.com/questions/28179835/compile-time-template-instantiation-check/28179884#28179884">Compile time template instantiation check</a> has an accepted answer that relies on the depicted behaviour of the old compilers. So answering this question will help to find out, whether the accepted solution is correct. </p>