You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

构建带形状与步幅的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

遇到的问题

  1. 添加resize()或访问器方法失败:无法识别shape_type、m_shape等内部类型和成员。
  2. 声明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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 18:47:33