xtensor
xtensor copied to clipboard
Example code from the page "Extending xtensor" gives "incomplete type"?
I'm trying to use xtensor for defining an image class with extra header information. The example Structures that embed shape and strides from the documentation page "Extending xtensor" comes very close to what I'm after. What I'm trying to do is have a class that also includes header information for loading NIfTI images (and provides file I/O for those).
Putting the code together in a program I had to change a few lines to reduce errors (for example, I could not find the struct m_raw
which was used in the example code and add a few forward class template declarations) but I got as far as compiling main()
.
However, now the compiler gives the error
/usr/bin/g++-12 -c "test-xtensor/main.cpp" -Wall -std=gnu++20 -gdwarf-2 -O0 -Wall -o ../build-Debug/test-xtensor/main.cpp.o -Iquantstack/include -I.
In file included from quantstack/include/xtensor/xcontainer.hpp:23,
from quantstack/include/xtensor/xarray.hpp:20,
from quantstack/include/xtensor/xadapt.hpp:20,
from test-xtensor/main.cpp:1:
quantstack/include/xtensor/xiterable.hpp: In instantiation of 'class xt::xconst_iterable<raw_tensor_adaptor<double> >':
bis/quantstack/include/xtensor/xiterable.hpp:151:11: required from 'class xt::xiterable<raw_tensor_adaptor<double> >'
bis/quantstack/include/xtensor/xiterable.hpp:311:11: required from 'class xt::xcontiguous_iterable<raw_tensor_adaptor<double> >'
bis/quantstack/include/xtensor/xcontainer.hpp:71:11: required from 'class xt::xcontainer<raw_tensor_adaptor<double> >'
test-xtensor/main.cpp:41:7: required from 'class raw_tensor_adaptor<double>'
test-xtensor/main.cpp:82:14: required from here
quantstack/include/xtensor/xiterable.hpp:43:15: error: invalid use of incomplete type 'struct xt::xiterable_inner_types<raw_tensor_adaptor<double> >'
43 | using inner_shape_type = typename iterable_types::inner_shape_type;
| ^~~~~~~~~~~~~~~~
quantstack/include/xtensor/xiterable.hpp:23:12: note: declaration of 'struct xt::xiterable_inner_types<raw_tensor_adaptor<double> >'
23 | struct xiterable_inner_types;
| ^~~~~~~~~~~~~~~~~~~~~
In the listing below
- line 41 is the definition of the
raw_tensor_adaptor
class - line 82 is where I call the constructor.
From the error it is not clear to me if the error is with the arguments to the call or the template parameters of the class? The call seems more likely as the class was mainly copied, but as mentioned I had to change some things to remove errors messages.
There are many similar errors (incomplete type) all referring to xtensor/xiterable.hpp
and xtensor/xcontainer.hpp
.
If anyone has built this example I would love to hear what the missing link is! Sorry that my 'minimal example' is so long.
code:
#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;
shape_type m_strides;
shape_type m_backstrides;
static constexpr xt::layout_type layout = xt::layout_type::dynamic;
};
template <class T>
class raw_tensor_adaptor;
template <class T>
struct xcontainer_inner_types;
template <class T>
struct 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 xt::layout_type layout = raw_tensor<T>::layout;
};
template <class T>
struct xiterable_inner_types;
template <class T>
struct xiterable_inner_types<raw_tensor_adaptor<T>>
: xt::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>> {
friend class base_type;
public:
using reference = T&;
using const_reference = const T&;
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); }
template <class... Args>
reference operator()(Args... args) { /* Should forward to table<T>:operator()(args...) */ }
template <class... Args>
const_reference operator()(Args... args) const { /* Should forward to table<T>::operator()(args...) */ }
reference operator[](const xt::xindex& index) { return element(index.cbegin(), index.cend()); }
const_reference operator[](const xt::xindex& index) const { return element(index.cbegin(), index.cend()); }
reference operator[](size_t i) { return operator()(i); }
const_reference operator[](size_t i) const { return operator()(i); }
template <class It>
reference element(It first, It last) { /* Should forward to table<T>::element(first, last) */ }
template <class It>
const_reference element(It first, It last) { /* Should forward to table<T>::element(first, last) */ }
protected:
base_type::inner_shape_type& shape_impl() { return base_type::m_shape; };
const base_type::inner_shape_type& shape_impl() const { return base_type::m_shape; };
base_type::inner_strides_type& strides_impl() { return base_type::m_strides; };
const base_type::inner_strides_type& strides_impl() const { return base_type::m_strides; };
base_type::inner_backstrides_type& backstrides_impl() { return base_type::m_backstrides; };
const base_type::inner_backstrides_type& backstrides_impl() const { return base_type::m_backstrides; };
public:
void resize(const base_type::shape_type& shape) {
if(base_type::m_shape != shape)
resize(shape, xt::layout_type::row_major);
}
void resize(const base_type::shape_type& shape, xt::layout_type l) {
base_type::m_shape = shape;
base_type::m_strides.resize(shape.size());
base_type::m_backstrides.resize(shape.size());
auto data_size = compute_strides(base_type::m_shape, l, base_type::m_strides, base_type::m_backstrides);
base_type::m_data.resize(data_size);
}
void resize(const base_type::shape_type& shape, const base_type::strides_type& strides) {
base_type::m_shape = shape;
base_type::m_strides = strides;
base_type::m_backstrides.resize(shape.size());
adapt_strides(base_type::m_shape, base_type::m_strides, base_type::m_backstrides);
base_type::m_data.resize(compute_size(base_type::m_shape));
}
};
int main() {
using tensor_type = raw_tensor_adaptor<double>;
auto v = std::vector<double> ( { 1, 2, 3, 4, 5 } );
tensor_type b (v), c(v), d(v);
tensor_type e = b + c - d;
return 0;
}