This one has me baffled.
Here's the sample code in its entirety:
#include <vector>
struct Unit {};
template <typename DataType>
class Vector : public std::vector<DataType>
{
  public:
  typedef std::vector<DataType> base_t;
    Vector() = default;
    explicit Vector(Unit const &units);
    bool check_class_invariant() const noexcept
    {
        return base_t::size() < 2;
    }
    operator Vector<DataType const>() const;
  private:
    Unit units_;
};
void foo()
{
    Vector<double> a;
    Vector<double> b(a);   // wants to construct Vector<double const> for some reason
}
This is a much boiled down version of code that actually does something interesting.
Compilation fails with g++ 8.1.0. The error messages indicate that the compiler is trying to instantiate Vector<double const> at the indicated line, which implies instantiating std::vector<double const>, which is forbidden by the standard.
Here's the full error message:
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<const double, std::allocator<const double> >â:
/home/kgbudge/src/core/src/utils/test/test.cc:6:7:   required from âclass Vector<const double>â
/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<typename remove_cv<_Tp>::type, _Tp>::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<typename _Alloc::value_type, _Tp>::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
Why is the compiler trying to instantiate Vector<double const>?
Clues: If I change the units_ member from struct Unit to int, the code compiles.
If I remove either the constructor taking a single struct Unit argument, or the conversion operator to Vector<DataType const>, the code compiles.
Any ideas what is happening here?
(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.)
(Further edit: See the comments for an explanation of the context for this question.
It looks like this may solve my problem:
struct Unit
{
};
template <typename DataType> class Vector;
template <typename DataType> class Vector<DataType const>;
template <typename DataType> class Vector : public std::vector<DataType>
{
  public:
    typedef std::vector<DataType> base_t;
    Vector() = default;
  //  explicit Vector(Unit const &units);
    bool check_class_invariant() const noexcept { return base_t::size() < 2; }
   operator Vector<DataType const>() const;
  private:
    Unit units_;
};
void foo()
{
    Vector<double> a;
    Vector<double> b(a); // wants to construct Vector<double const>
}
The code now builds, because presumably no attempt is made to instantiate  operator Vector<double const> if it is unused and if Vector<double const> is declared as a specialization but not (yet) defined.
I'm not sure how reliable this is, though.)
(Further further edit: No, not reliable. The translation system is determined to try to instantiate Vector<double const> if Vector<double const> appears as a completed type anywhere in the Vector<double> interface, whether I intend to use that part of the interface or not.
And to close this discussion: The context is that Vector was originally written to use a different underlying container than std::vector, and it worked fine since that container supported const element types. I was tasked to try to extend this to work with std::vector as the underlying container. Having an operator Vector<Database double> 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 std::vector as the underlying container.
Unless my team decides I should write a specialization just for std::vector. Sigh)
 
    