构建带形状与步幅的std::vector的xtensor适配器遇编译错误求助
自定义xtensor容器:解决raw_tensor_adaptor编译与功能问题
问题背景
基于xtensor「嵌入形状和步幅的结构」示例实现自定义带头部信息的图像类,当前代码可正常声明raw_tensor<double>对象,但在声明raw_tensor_adaptor<double>实例或添加resize等方法时出现编译错误。
原始代码
#include <xtensor/xadapt.hpp> #include <xtensor/xstrides.hpp> template <class T> struct raw_tensor { using container_type = std::vector<T>; using shape_type = std::vector<std::size_t>; container_type m_data; shape_type m_shape, m_strides, m_backstrides; static constexpr xt::layout_type layout = xt::layout_type::dynamic; }; template <class T> class raw_tensor_adaptor; template <class T> struct xt::xcontainer_inner_types<raw_tensor_adaptor<T>> { using container_type = typename raw_tensor<T>::container_type; using inner_shape_type = typename raw_tensor<T>::shape_type; using inner_strides_type = inner_shape_type; using inner_backstrides_type = inner_shape_type; using shape_type = inner_shape_type; using strides_type = inner_shape_type; using backstrides_type = inner_shape_type; static constexpr layout_type layout = raw_tensor<T>::layout; }; template <class T> struct xt::xiterable_inner_types<raw_tensor_adaptor<T>> : xcontainer_iterable_types<raw_tensor_adaptor<T>> { }; template <class T> class raw_tensor_adaptor : public xt::xcontainer<raw_tensor_adaptor<T>>, public xt::xcontainer_semantic<raw_tensor_adaptor<T>> { public: using self_type = raw_tensor_adaptor<T>; using base_type = xt::xcontainer<self_type>; using semantic_base = xt::xcontainer_semantic<self_type>; raw_tensor_adaptor(const raw_tensor_adaptor&) = default; raw_tensor_adaptor& operator=(const raw_tensor_adaptor&) = default; raw_tensor_adaptor(raw_tensor_adaptor&&) = default; raw_tensor_adaptor& operator=(raw_tensor_adaptor&&) = default; template <class E> raw_tensor_adaptor(const xt::xexpression<E>& e) : base_type() { semantic_base::assign(e); } template <class E> self_type& operator=(const xt::xexpression<E>& e) { return semantic_base::operator=(e); } }; int main() { raw_tensor<double> i,j,k; // this works using tensor_type = raw_tensor_adaptor<double>; // tensor_type a, b, c; // but not this if un-commented // .... init a, b, c // tensor_type d = a + b - c; raw_tensor < int > a; return 0; }
编译环境与命令
Linux(GCC-11)环境下编译命令:
$ cd /tmp && mkdir -p xtensor-test && cd xtensor-test $ git clone https://github.com/xtensor-stack/xtensor.git $ git clone https://github.com/xtensor-stack/xtl.git $ vi xtensor-test.cpp # insert the code block above and save $ g++ -o xtensor-test xtensor-test.cpp -Ixtensor/include -Ixtl/include
遇到的问题
- 添加resize()或访问器方法失败:无法识别
shape_type、m_shape等内部类型和成员。 - 声明raw_tensor_adaptor实例编译错误:出现大量类型缺失、无默认构造函数的错误,核心错误片段如下:
include/xtensor/xiterable.hpp:288:19: error: no type named 'xexpression_type' in 'struct xt::xcontainer_inner_types<raw_tensor_adaptor<double> >’ include/xtensor/xaccessible.hpp:35:15: error: no type named 'reference' in 'struct xt::xcontainer_inner_types<raw_tensor_adaptor<double> >’ include/xtensor/xaccessible.hpp:36:15: error: no type named 'const_reference' in 'struct xt::xcontainer_inner_types<raw_tensor_adaptor<double> >’ include/xtensor/xcontainer.hpp:79:15: error: no type named 'storage_type' in 'struct xt::xcontainer_inner_types<raw_tensor_adaptor<double> >' xtensor-test.cpp:70:13: error: no matching function for call to ‘raw_tensor_adaptor<double>::raw_tensor_adaptor()’
解决方法
1. 补全xcontainer_inner_types的必填类型
xtensor的xcontainer_inner_types需要定义基类依赖的所有类型,补充缺失的类型定义:
template <class T> struct xt::xcontainer_inner_types<raw_tensor_adaptor<T>> { using container_type = typename raw_tensor<T>::container_type; using inner_shape_type = typename raw_tensor<T>::shape_type; using inner_strides_type = inner_shape_type; using inner_backstrides_type = inner_shape_type; using shape_type = inner_shape_type; using strides_type = inner_shape_type; using backstrides_type = inner_shape_type; // 补充缺失的类型 using storage_type = container_type; using reference = typename container_type::reference; using const_reference = typename container_type::const_reference; using size_type = typename container_type::size_type; using xexpression_type = xt::xexpression<raw_tensor_adaptor<T>>; using temporary_type = xt::xtensor<T, xt::dynamic_layout>; static constexpr layout_type layout = raw_tensor<T>::layout; };
2. 给raw_tensor_adaptor添加数据成员与核心接口
raw_tensor_adaptor需要持有raw_tensor实例,并实现xtensor基类要求的shape()、strides()、backstrides()、data()等方法,同时添加默认构造函数:
template <class T> class raw_tensor_adaptor : public xt::xcontainer<raw_tensor_adaptor<T>>, public xt::xcontainer_semantic<raw_tensor_adaptor<T>> { public: using self_type = raw_tensor_adaptor<T>; using base_type = xt::xcontainer<self_type>; using semantic_base = xt::xcontainer_semantic<self_type>; using raw_tensor_type = raw_tensor<T>; using shape_type = typename raw_tensor_type::shape_type; using container_type = typename raw_tensor_type::container_type; // 添加默认构造函数 raw_tensor_adaptor() = default; raw_tensor_adaptor(const raw_tensor_adaptor&) = default; raw_tensor_adaptor& operator=(const raw_tensor_adaptor&) = default; raw_tensor_adaptor(raw_tensor_adaptor&&) = default; raw_tensor_adaptor& operator=(raw_tensor_adaptor&&) = default; // 从raw_tensor构造 explicit raw_tensor_adaptor(raw_tensor_type rt) : m_raw_tensor(std::move(rt)) {} template <class E> raw_tensor_adaptor(const xt::xexpression<E>& e) : base_type() { semantic_base::assign(e); } template <class E> self_type& operator=(const xt::xexpression<E>& e) { return semantic_base::operator=(e); } // 实现xtensor要求的核心接口 const shape_type& shape() const noexcept { return m_raw_tensor.m_shape; } shape_type& shape() noexcept { return m_raw_tensor.m_shape; } const shape_type& strides() const noexcept { return m_raw_tensor.m_strides; } shape_type& strides() noexcept { return m_raw_tensor.m_strides; } const shape_type& backstrides() const noexcept { return m_raw_tensor.m_backstrides; } shape_type& backstrides() noexcept { return m_raw_tensor.m_backstrides; } container_type& data() noexcept { return m_raw_tensor.m_data; } const container_type& data() const noexcept { return m_raw_tensor.m_data; } // 添加resize方法示例 void resize(const shape_type& s) { m_raw_tensor.m_shape = s; m_raw_tensor.m_strides = xt::compute_strides(s, raw_tensor_type::layout); m_raw_tensor.m_backstrides = xt::compute_backstrides(s, m_raw_tensor.m_strides); m_raw_tensor.m_data.resize(xt::compute_size(s)); } private: raw_tensor_type m_raw_tensor; };
3. 完整修正后的代码
#include <xtensor/xadapt.hpp> #include <xtensor/xstrides.hpp> #include <xtensor/xtensor.hpp> template <class T> struct raw_tensor { using container_type = std::vector<T>; using shape_type = std::vector<std::size_t>; container_type m_data; shape_type m_shape, m_strides, m_backstrides; static constexpr xt::layout_type layout = xt::layout_type::dynamic; }; template <class T> class raw_tensor_adaptor; template <class T> struct xt::xcontainer_inner_types<raw_tensor_adaptor<T>> { using container_type = typename raw_tensor<T>::container_type; using inner_shape_type = typename raw_tensor<T>::shape_type; using inner_strides_type = inner_shape_type; using inner_backstrides_type = inner_shape_type; using shape_type = inner_shape_type; using strides_type = inner_shape_type; using backstrides_type = inner_shape_type; using storage_type = container_type; using reference = typename container_type::reference; using const_reference = typename container_type::const_reference; using size_type = typename container_type::size_type; using xexpression_type = xt::xexpression<raw_tensor_adaptor<T>>; using temporary_type = xt::xtensor<T, xt::dynamic_layout>; static constexpr layout_type layout = raw_tensor<T>::layout; }; template <class T> struct xt::xiterable_inner_types<raw_tensor_adaptor<T>> : xcontainer_iterable_types<raw_tensor_adaptor<T>> { }; template <class T> class raw_tensor_adaptor : public xt::xcontainer<raw_tensor_adaptor<T>>, public xt::xcontainer_semantic<raw_tensor_adaptor<T>> { public: using self_type = raw_tensor_adaptor<T>; using base_type = xt::xcontainer<self_type>; using semantic_base = xt::xcontainer_semantic<self_type>; using raw_tensor_type = raw_tensor<T>; using shape_type = typename raw_tensor_type::shape_type; using container_type = typename raw_tensor_type::container_type; raw_tensor_adaptor() = default; raw_tensor_adaptor(const raw_tensor_adaptor&) = default; raw_tensor_adaptor& operator=(const raw_tensor_adaptor&) = default; raw_tensor_adaptor(raw_tensor_adaptor&&) = default; raw_tensor_adaptor& operator=(raw_tensor_adaptor&&) = default; explicit raw_tensor_adaptor(raw_tensor_type rt) : m_raw_tensor(std::move(rt)) {} template <class E> raw_tensor_adaptor(const xt::xexpression<E>& e) : base_type() { semantic_base::assign(e); } template <class E> self_type& operator=(const xt::xexpression<E>& e) { return semantic_base::operator=(e); } const shape_type& shape() const noexcept { return m_raw_tensor.m_shape; } shape_type& shape() noexcept { return m_raw_tensor.m_shape; } const shape_type& strides() const noexcept { return m_raw_tensor.m_strides; } shape_type& strides() noexcept { return m_raw_tensor.m_strides; } const shape_type& backstrides() const noexcept { return m_raw_tensor.m_backstrides; } shape_type& backstrides() noexcept { return m_raw_tensor.m_backstrides; } container_type& data() noexcept { return m_raw_tensor.m_data; } const container_type& data() const noexcept { return m_raw_tensor.m_data; } void resize(const shape_type& s) { m_raw_tensor.m_shape = s; m_raw_tensor.m_strides = xt::compute_strides(s, raw_tensor_type::layout); m_raw_tensor.m_backstrides = xt::compute_backstrides(s, m_raw_tensor.m_strides); m_raw_tensor.m_data.resize(xt::compute_size(s)); } private: raw_tensor_type m_raw_tensor; }; int main() { raw_tensor<double> i,j,k; using tensor_type = raw_tensor_adaptor<double>; // 测试默认构造与resize tensor_type a; a.resize({2,3}); a(0,0) = 1.0; a(1,2) = 5.0; // 测试表达式运算 tensor_type b = a * 2; tensor_type c = a + b; return 0; }
4. 验证编译与运行
使用原编译命令即可正常编译:
$ g++ -o xtensor-test xtensor-test.cpp -Ixtensor/include -Ixtl/include $ ./xtensor-test
内容的提问来源于stack exchange,提问作者alle_meije
相关产品推荐
相关产品推荐

