title: C++ compilers diverge in encapsulation behavior - which one gets it right?
body: <p>Compilers (<code>clang-5.0.0</code>, <code>GCC-7.3</code>, <code>ICC-18</code> and <code>MSVC-19</code>) diverge w.r.t. accessibility of members of <code>A</code> below.</p>
  
  <pre><code>class A {
  
      template &lt;class&gt; static constexpr int f() { return 0; }
  
      template &lt;int&gt; struct B {};
  
      template &lt;class T&gt; using C = B&lt;f&lt;T&gt;()&gt;;
  
  };
  </code></pre>
  
  <p>Indeed, consider the following usages:</p>
  
  <pre><code>template &lt;class T&gt; using D = A::C&lt;T&gt;;
  
  int main() {
                          //    | clang | gcc | icc | msvc
      (void) A::f&lt;int&gt;(); // 1: | f     | f   | f   | f, (C)
      (void) A::B&lt;0&gt;{};   // 2: | B     |     | B   | B, (C)
      (void) A::C&lt;int&gt;{}; // 3: | C,  f |     | C   | C
      (void) D&lt;int&gt;{};    // 4: | f     |     | C   | C
  }
  </code></pre>
  
  <p>The table on the right shows which members each compiler requires to be made public to accept the code (when compiled for C++14).</p>
  
  <p>IMHO, ICC and MSVC (ignoring <code>(C)</code> entries) look correct. Except for the first line, GCC seems to be completely ignoring accessibility.</p>
  
  <p>I disagree with clang when it requires <code>f</code> to be public to instantiate  <code>A::C&lt;int&gt;</code> and <code>D&lt;int&gt;</code>. Like ICC and MSVC, I think <code>C</code> and only <code>C</code> needs to be public. It is true that <code>C</code> uses <code>f</code> but is it not an implementation detail? Notice that <code>C</code> also uses <code>B</code>. If clang were correct, then why does it not require <code>B</code> to be public as well?</p>
  
  <p>Finally, let us consider the <code>(C)</code> entries. MSVC requires <code>C</code> to be public when it first encounters the definition of <code>D</code>, that is, MSVC complains about <code>C</code> being private.</p>
  
  <h3>My questions are:</h3>
  
  <ol>
  <li>Am I right (and so is ICC) in my analysis? Otherwise which other compiler is correct and why?</li>
  <li>Is the MSVC issue yet another incarnation of 
  <a href="https://stackoverflow.com/questions/6273176/what-exactly-is-broken-with-microsoft-visual-cs-two-phase-template-instanti">two-phase instantiation bug in msvc</a>?</li>
  </ol>
  
  <p><strong>Update</strong>: Regarding GCC, this seems to be the bug reported in comment 8, <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41437#c8" rel="nofollow noreferrer">here</a>.</p>