编译器尝试实例化std :: vector <double const =“”>没有明显的原因

时间:2019-03-22 16:20:52

标签: c++

这个让我感到困惑。

这是完整的示例代码:


#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
}

这是一个精简的代码版本,实际上可以做一些有趣的事情。

在g ++ 8.1.0中编译失败。错误消息表明编译器正在尝试在指示的行上实例化Vector<double const>,这意味着实例化std::vector<double const>,这是标准所禁止的。

这是完整的错误消息:

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

为什么编译器试图实例化Vector<double const>

线索:如果我将units_成员从struct Unit更改为int,则代码会编译。

如果我删除带有单个struct Unit参数的构造函数或Vector<DataType const>的转换运算符,则代码将编译。

任何想法在这里发生了什么?

(编辑:我的问题不是为什么不能为double const实例化std :: vector。这就是为什么编译器首先尝试实例化std :: vector的原因。)

(进一步编辑:有关此问题的上下文说明,请参见注释。

看起来这可以解决我的问题:


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>
}

现在可以构建代码,因为如果没有使用operator Vector<double const>Vector<double const>被声明为特殊化但尚未定义,则大概不会尝试实例化Vector<double const>

不过,我不确定这是否可靠。

(进一步编辑:否,不可靠。如果Vector<double const>出现在Vector<double>界面中的任何位置,则翻译系统将尝试实例化Vector打算使用或不使用界面的那一部分。

并结束本次讨论:上下文是std::vector最初被编写为使用与const不同的基础容器,并且由于该容器支持std::vector元素类型,因此可以很好地工作。我受命尝试将其扩展为与operator Vector<Database double>作为基础容器一起使用。对于原始的基础容器类型,必须有一个std::vector,但我仍然必须支持它,并且不能丢弃它。因此,答案是我无法将其扩展为std::vector作为基础容器。

除非我的团队决定我只为{{1}}写一个专长。 叹气

2 个答案:

答案 0 :(得分:0)

因此解决方案是为const元素声明我的类的专业化,但从不定义它,因为我从不打算使用它。这样可以正确构建,链接和运行。

它避免摆脱转换运算符,而我正是原始基础容器类型所需要的。

答案 1 :(得分:-1)

要实例化您的类型,必须可以实例化operator Vector<DataType const>() const

而且,为此,必须实例化Vector<DataType const>,而不是实例化,因为您不能具有const std::vector值类型。

只需删除该运算符即可: