这个让我感到困惑。
这是完整的示例代码:
#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}}写一个专长。 叹气)
答案 0 :(得分:0)
因此解决方案是为const元素声明我的类的专业化,但从不定义它,因为我从不打算使用它。这样可以正确构建,链接和运行。
它避免摆脱转换运算符,而我正是原始基础容器类型所需要的。
答案 1 :(得分:-1)
要实例化您的类型,必须可以实例化operator Vector<DataType const>() const
。
而且,为此,必须实例化Vector<DataType const>
,而不是实例化,因为您不能具有const
std::vector
值类型。
只需删除该运算符即可: