As the parameter N is a non-type template parameter, it must be a value known at compile time. 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.
You can work around this by using containers such as std::variant and std::any. They make it possible to store an object of a type from either a closed set of types or any type respectively. As an example, you could use std::any to create a helper tensor_holder class like the following:
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. 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).
Assuming you have a small set of possible tensor sizes, you could run different branches inside your function like this:
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. 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:
use_tensor(Eigen::Tensor<double, 3>{});
(godbolt)