c++ - 编译器无缘无故地尝试实例化 std::vector<double const>

标签 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的成员(member)至 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>界面的任何地方,我是否打算使用那部分接口(interface)与否。

结束讨论:上下文是 Vector最初是为了使用与 std::vector 不同的底层容器而编写的,并且它工作正常,因为该容器支持 const元素类型。我的任务是尝试扩展它以使用 std::vector作为底层容器。有一个 operator Vector<Database double>是对原始底层容器类型的必要要求,我仍然必须支持它,我不能丢弃它。所以答案是我不能将其扩展到 std::vector作为底层容器。

除非我的团队决定我应该只为 std::vector 编写特化. 叹息)

最佳答案

所以解决方案是为 const 元素声明我的类的特化,但从不定义它,因为我从来没有打算使用它。这会正确构建、链接和运行。

它避免了去掉转换运算符,这是我需要的原始底层容器类型。

关于c++ - 编译器无缘无故地尝试实例化 std::vector<double const>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55303860/

相关文章:

c++ - 使用 QTcpSocket 发送字节

c++ - 是否可以让 C++ 方法在不重载方法的情况下接受 const char* 和 const wchar_t* 作为参数?

c++ - 如何使用在包含使用符号的文件的文件中声明的符号(函数、字段、类等)。 C++

c++ - 删除后访问指针

c++ - 基于文本的冒险游戏

c++ - 如何使用循环将 vector 插入队列<vector<int>>?

c++ - 时间复杂度为 `std::partition()`

c++ - 从动态分配的解引用指针默认初始化非常量引用函数参数是否会造成内存泄漏?

c++ - 为什么 trunc() 返回 0?

c++ - 我有一个关于将 std::array 传递给函数的问题