这个让我感到困惑。
完整的示例代码如下:
#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/