[英]How to declare a tensor with Eigen without specifying the dimension?
I have a function that takes as input a tensor of dimension n, I have to store this tensor to reuse it later.我有一个 function 将 n 维张量作为输入,我必须存储这个张量以便以后重用。 However, I don't know in advance the dimension of my tensor.但是,我事先不知道我的张量的维度。 I would like to do this:我想这样做:
//in class.h
Eigen::Tensor<double, N> mytensor;
//in class.cpp
mytensor = input;
Is there a way to do this?有没有办法做到这一点?
As the parameter N
is a non-type template parameter, it must be a value known at compile time.由于参数N
是非类型模板参数,因此它必须是编译时已知的值。 This means that you cannot really store an Eigen::Tensor
with unspecified N
in a variable, as each instantiation with a different size is a different type.这意味着您不能真正将具有未指定N
的Eigen::Tensor
存储在变量中,因为每个具有不同大小的实例化都是不同的类型。
You can work around this by using containers such as std::variant
and std::any
.您可以使用诸如std::variant
和std::any
之类的容器来解决此问题。 They make it possible to store an object of a type from either a closed set of types or any type respectively.它们可以分别存储来自封闭类型集或任何类型的类型的 object。 As an example, you could use std::any
to create a helper tensor_holder
class like the following:例如,您可以使用std::any
创建一个助手tensor_holder
class,如下所示:
template <typename T>
class tensor_holder
{
private:
std::any _held;
size_t _size;
public:
template <int N>
constexpr tensor_holder(Eigen::Tensor<T, N> tensor) :
_held{std::move(tensor)},
_size{N}
{
}
constexpr tensor_holder(const tensor_holder&) = default;
constexpr tensor_holder(tensor_holder&&) = default;
template <size_t N>
Eigen::Tensor<T, N>& get()
{
return std::any_cast<Eigen::Tensor<T, N>&>(_held);
}
template <size_t N>
const Eigen::Tensor<T, N>& get() const
{
return std::any_cast<Eigen::Tensor<T, N>&>(_held);
}
constexpr int size() const noexcept
{
return _size;
}
};
It stores an Eigen::Tensor
of any size inside an std::any
.它将任意大小的Eigen::Tensor
存储在std::any
中。 The member function get
throws std::bad_any_cast
if the provided size doesn't match the real tensor size (note that the limitation of the size being a compile time value doesn't go away).如果提供的大小与实际张量大小不匹配,则成员 function get
throws std::bad_any_cast
(请注意,作为编译时间值的大小限制不会 go 离开)。
Assuming you have a small set of possible tensor sizes, you could run different branches inside your function like this:假设您有一小组可能的张量大小,您可以在 function 中运行不同的分支,如下所示:
void use_tensor(const tensor_holder<double>& in)
{
static tensor_holder held = in; // it can be stored for later
if (held.size() == 4)
{
auto& tensor = held.get<4>();
tensor(0, 1, 2, 3) = 115.5;
}
else if (held.size() == 3)
{
// some other logic
}
}
You could also use a switch
instead of an if
in this case.在这种情况下,您也可以使用switch
而不是if
。 This solution is practical only if the number of different tensor sizes you have to support is small.仅当您必须支持的不同张量大小的数量很少时,此解决方案才实用。 I don't know how you plan to use your tensor, so it's hard for me to say whether this solution is adequate.我不知道你打算如何使用你的张量,所以我很难说这个解决方案是否足够。
Thanks to the converting constructor of class tensor_holder
, you can call the function by simply providing it an Eigen::Tensor
with any size:由于 class tensor_holder
的转换构造函数,您可以通过简单地提供任意大小的Eigen::Tensor
来调用 function:
use_tensor(Eigen::Tensor<double, 3>{});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.