title: incomplete types with std::map and std::variant
body: <p>Consider this simplified and very specific implementation of a recursive variant on top of <code>std::variant</code>:</p>
  
  <pre><code>#include &lt;map&gt;
  #include &lt;variant&gt;
  
  struct recursive_tag;
  
  template &lt;typename...&gt;
  struct RecursiveVariant;
  
  template &lt;&gt;
  struct RecursiveVariant&lt;int, std::map&lt;int, recursive_tag&gt;&gt;
      : std::variant&lt;int, std::map&lt;int, RecursiveVariant&lt;int, std::map&lt;int, recursive_tag&gt;&gt;&gt;&gt;
  {
      using underlying = std::variant&lt;int,
            std::map&lt;int, RecursiveVariant&lt;int, std::map&lt;int, recursive_tag&gt;&gt;&gt;&gt;;
      using underlying::underlying;
  };
  
  
  int main() {
      RecursiveVariant&lt;int, std::map&lt;int, recursive_tag&gt;&gt; rv; 
  }
  </code></pre>
  
  <p>This fails to compile on gcc 7/8 due to trying to instantiate <code>std::pair&lt;const int, recursive_tag&gt;</code>, which itself fails because <code>recursive_tag</code> is an incomplete type. </p>
  
  <p>But, nothing in the compiler error call-stack indicates to me <em>why</em> <code>std::pair&lt;const int, recursive_tag&gt;</code> needs to be instantiated. The top line there is:</p>
  
  <blockquote>
    <p>variant:252:48:   required from ‘<code>void std::__detail::__variant::__erased_dtor(_Variant&amp;&amp;) [with _Variant = const std::__detail::__variant::_Variant_storage&lt;false, int, std::map&lt;int, RecursiveVariant&lt;int, std::map&lt;int, recursive_tag, std::less&lt;int&gt;, std::allocator&lt;std::pair&lt;const int, recursive_tag&gt; &gt; &gt; &gt;, std::less&lt;int&gt;, std::allocator&lt;std::pair&lt;const int, RecursiveVariant&lt;int, std::map&lt;int, recursive_tag, std::less&lt;int&gt;, std::allocator&lt;std::pair&lt;const int, recursive_tag&gt; &gt; &gt; &gt; &gt; &gt; &gt; &gt;&amp;; long unsigned int _Np = 0]</code>’</p>
  </blockquote>
  
  <p>pointing to:</p>
  
  <pre><code>249   template&lt;typename _Variant, size_t _Np&gt;
  250     void
  251     __erased_dtor(_Variant&amp;&amp; __v)
  252     { std::_Destroy(std::__addressof(__get&lt;_Np&gt;(__v))); }
  </code></pre>
  
  <p>While type <code>map&lt;int, recursive_tag&gt;</code> is spelled in there, the actual <code>map</code> type that should be instantiated is <code>map&lt;int, RecursiveVariant&lt;int, map&lt;int, recursive_tag&gt;&gt;&gt;</code>... which should only necessitate the instantiation of <code>pair&lt;const int, RecursiveVariant&lt;...&gt;&gt;</code>. </p>
  
  <p>Simply making <code>recursive_tag</code> complete (i.e. by adding <code>{}</code>) fixes the problem. But what causes the problem to begin with?</p>