title: Compiler trying to instantiate std::vector<double const> for no obvious reason
body: <p>This one has me baffled.</p>
  
  <p>Here's the sample code in its entirety:</p>
  
  <hr>
  
  <pre><code>#include &lt;vector&gt;
  
  struct Unit {};
  
  template &lt;typename DataType&gt;
  class Vector : public std::vector&lt;DataType&gt;
  {
    public:
    typedef std::vector&lt;DataType&gt; base_t;
  
      Vector() = default;
  
      explicit Vector(Unit const &amp;units);
  
      bool check_class_invariant() const noexcept
      {
          return base_t::size() &lt; 2;
      }
  
      operator Vector&lt;DataType const&gt;() const;
  
    private:
      Unit units_;
  };
  
  void foo()
  {
      Vector&lt;double&gt; a;
      Vector&lt;double&gt; b(a);   // wants to construct Vector&lt;double const&gt; for some reason
  }
  </code></pre>
  
  <hr>
  
  <p>This is a much boiled down version of code that actually does something interesting.</p>
  
  <p>Compilation fails with g++ 8.1.0. The error messages indicate that the compiler is trying to instantiate <code>Vector&lt;double const&gt;</code> at the indicated line, which implies instantiating <code>std::vector&lt;double const&gt;</code>, which is forbidden by the standard.</p>
  
  <p>Here's the full error message:</p>
  
  <pre><code>In file included from /scratch/vendors/spack.20180425/opt/spack/linux-rhel7-x86_64/gcc-4.8.5/gcc-8.1.0-3c5hjkqndywdp3w2l5vts62xlllrsbtq/include/c++/8.1.0/vector:64,
                   from /home/kgbudge/src/core/src/utils/test/test.cc:1:
  /scratch/vendors/spack.20180425/opt/spack/linux-rhel7-x86_64/gcc-4.8.5/gcc-8.1.0-3c5hjkqndywdp3w2l5vts62xlllrsbtq/include/c++/8.1.0/bits/stl_vector.h: In instantiation of âclass std::vector&lt;const double, std::allocator&lt;const double&gt; &gt;â:
  /home/kgbudge/src/core/src/utils/test/test.cc:6:7:   required from âclass Vector&lt;const double&gt;â
  /home/kgbudge/src/core/src/utils/test/test.cc:30:23:   required from here
  /scratch/vendors/spack.20180425/opt/spack/linux-rhel7-x86_64/gcc-4.8.5/gcc-8.1.0-3c5hjkqndywdp3w2l5vts62xlllrsbtq/include/c++/8.1.0/bits/stl_vector.h:351:21: error: static assertion failed: std::vector must have a non-const, non-volatile value_type
         static_assert(is_same&lt;typename remove_cv&lt;_Tp&gt;::type, _Tp&gt;::value,
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /scratch/vendors/spack.20180425/opt/spack/linux-rhel7-x86_64/gcc-4.8.5/gcc-8.1.0-3c5hjkqndywdp3w2l5vts62xlllrsbtq/include/c++/8.1.0/bits/stl_vector.h:354:21: error: static assertion failed: std::vector must have the same value_type as its allocator
         static_assert(is_same&lt;typename _Alloc::value_type, _Tp&gt;::value,
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  make[2]: *** [src/utils/test/CMakeFiles/Ut_utils_test_exe.dir/test.cc.o] Error 1
  make[1]: *** [src/utils/test/CMakeFiles/Ut_utils_test_exe.dir/all] Error 2
  </code></pre>
  
  <p>Why is the compiler trying to instantiate <code>Vector&lt;double const&gt;</code>?</p>
  
  <p>Clues: If I change the <code>units_</code> member from <code>struct Unit</code> to <code>int</code>, the code compiles.</p>
  
  <p>If I remove either the constructor taking a single <code>struct Unit</code> argument, or the conversion operator to <code>Vector&lt;DataType const&gt;</code>, the code compiles.</p>
  
  <p>Any ideas what is happening here? </p>
  
  <p>(edit: My question is not why std::vector cannot be instantiated for double const. It is why the compiler is trying to instantiate std::vector in the first place.)</p>
  
  <p>(Further edit: See the comments for an explanation of the context for this question.</p>
  
  <p>It looks like this may solve my problem:</p>
  
  <pre><code>
  struct Unit
  {
  };
  
  template &lt;typename DataType&gt; class Vector;
  template &lt;typename DataType&gt; class Vector&lt;DataType const&gt;;
  
  template &lt;typename DataType&gt; class Vector : public std::vector&lt;DataType&gt;
  {
    public:
      typedef std::vector&lt;DataType&gt; base_t;
  
      Vector() = default;
  
    //  explicit Vector(Unit const &amp;units);
  
      bool check_class_invariant() const noexcept { return base_t::size() &lt; 2; }
  
     operator Vector&lt;DataType const&gt;() const;
  
    private:
      Unit units_;
  };
  
  void foo()
  {
      Vector&lt;double&gt; a;
      Vector&lt;double&gt; b(a); // wants to construct Vector&lt;double const&gt;
  }
  </code></pre>
  
  <p>The code now builds, because presumably no attempt is made to instantiate  <code>operator Vector&lt;double const&gt;</code> if it is unused and if <code>Vector&lt;double const&gt;</code> is declared as a specialization but not (yet) defined.</p>
  
  <p>I'm not sure how reliable this is, though.)</p>
  
  <p>(Further further edit: No, not reliable. The translation system is determined to try to instantiate <code>Vector&lt;double const&gt;</code> if <code>Vector&lt;double const&gt;</code> appears as a completed type anywhere in the <code>Vector&lt;double&gt;</code> interface, whether I intend to use that part of the interface or not.</p>
  
  <p>And to close this discussion: The context is that <code>Vector</code> was originally written to use a different underlying container than <code>std::vector</code>, and it worked fine since that container supported <code>const</code> element types. I was tasked to try to extend this to work with <code>std::vector</code> as the underlying container. Having an <code>operator Vector&lt;Database double&gt;</code> was a necessary requirement for the original underlying container type, which I must still support, and I can't discard it. So the answer is that I can't extend this to <code>std::vector</code> as the underlying container.</p>
  
  <p>Unless my team decides I should write a specialization just for <code>std::vector</code>. <em>Sigh</em>)</p>