title: Well-formed program containing an ill-formed template member function?
body: <p>In the snippet below, I'm puzzled about why the definition of <code>Wrapper::f() const</code> does not make my program ill-formed<sup>1</sup> although it calls a non-const member function of a non mutable member variable:</p>
  
  <pre><code>// well-formed program (???)
  // build with: g++ -std=c++17 -Wall -Wextra -Werror -pedantic
  template&lt;class T&gt; struct Data { void f() {} };
  
  template&lt;class T&gt; struct Wrapper
  {
      Data&lt;T&gt; _data;
      void f() const { _data.f(); } // _data.f(): non-const!
  };
  
  int main()
  {
      Wrapper&lt;void&gt; w; // no error in instantiation point?
      (void) w;
  }
  </code></pre>
  
  <p><kbd><a href="http://coliru.stacked-crooked.com/a/8cd26e2129d114b5" rel="noreferrer">demo</a></kbd><sup>2</sup></p>
  
  <p>On the other hand, if <code>Data</code> is a non template class<sup>3</sup>, a diagnostic is issued by my compiler:</p>
  
  <pre><code>// ill-formed program (as expected)
  // build with: g++ -std=c++17 -Wall -Wextra -Werror -pedantic
  struct Data { void f() {} };
  
  template&lt;class T&gt; struct Wrapper
  {
      Data _data;
      void f() const { _data.f(); } //error: no matching function for call to 'Data::f() const'
  };
  
  int main()
  {
      Wrapper&lt;void&gt; w;
      (void) w;
  }
  </code></pre>
  
  <p><kbd><a href="http://coliru.stacked-crooked.com/a/03742f915020763c" rel="noreferrer">demo</a></kbd></p>
  
  <p>I feel like the answer will contain expressions such as "deduced context" ... but I really cannot pin down the exact part of the standard scecifying this behaviour.</p>
  
  <p><strong>Is there a language lawyer to enlighten me on the matter?</strong></p>
  
  <hr>
  
  <p>Notes:<br>
   <sup>1)</sup> But I get an error if I try and effectively <em>call</em> <code>Wrapper&lt;T&gt;::f() const</code>.<br>
   <sup>2)</sup> I've compiled with <code>-std=c++17</code> but this is not specific to C++17, hence no specific tag.<br>
   <sup>3)</sup> In <a href="https://stackoverflow.com/a/31328843/5470596">this answer</a>, @Baum mit Augen quotes <code>[N4140, 14.7.1(2)]</code>:</p>
  
  <blockquote>
    <p>the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist</p>
  </blockquote>
  
  <p>but here in the compiling snippet (#2) <code>void f() const { _data.f(); }</code> fails although its <em>"specialization is <strong>never</strong> referenced in a context that requires the member definition to exist"</em>.</p>