I have a compile time tensor class. Now i would like to implement index access like this:
std::array<std::array<std::array<int, 3>, 2>, 1> myTensor;
template <class... Indices>
auto get(Indices... indices) {
return myTensor[indices][...];
}
int main() {
myTensor[0][1][2] = 3;
std::cout << get(0, 1, 2) << std::endl;
}
But this sadly does not compile. Does anyone have an idea of how i could implement this? It also needs to work when my tensor is const. I would also be fine using tuple instead of variadic template. I can use the most modern compiler/cpp standard if needed.
CodePudding user response:
You cannot fold over []
(for multidimensional indexing). You can achieve this with a pair of functions:
// This is written as generically as possible, but can be
// pared down by removing forwarding in your use case
template <class Container>
constexpr decltype(auto) get_of(Container&& c) noexcept {
return std::forward<Container>(c);
}
template <class Container, class Index, class... Indices>
constexpr decltype(auto) get_of(Container&& c, Index&& index, Indices&&... indices) {
return ::get_of(std::forward<Container>(c)[std::forward<Index>(index)], std::forward<Indices>(indices)...);
}
// Your attempt with `myTensor[indices][...]` becomes `get_of(myTensor, indices...)`
template <class... Indices>
decltype(auto) get(Indices... indices) {
return get_of(myTensor, indices...);
}
And if you are using C 2b, you can use operator[]
with multiple arguments, which might make it easier to use:
struct tensor_type {
std::array<std::array<std::array<int, 3>, 2>, 1> myTensor;
decltype(auto) operator[](auto... indices) {
return get_of(myTensor, indices...);
}
};
int main() {
tensor_type t;
t[0][1][2] = 3;
std::cout << t[0, 1, 2] << '\n';
}
CodePudding user response:
You can use C 20 <ranges>
to flatten a multidimensional array
#include <array>
#include <ranges>
#include <iostream>
std::array<std::array<std::array<int, 3>, 2>, 3> myTensor;
template <class... Indices>
auto& get(Indices... indices) {
return (std::span(&myTensor, 1) |
(std::views::transform(
[&](auto& r) -> auto& { return r[indices];
}) | ...))[0];
}
int main() {
myTensor[0][1][2] = 3;
myTensor[2][1][1] = 7;
std::cout << get(0, 0, 0) << std::endl;
std::cout << get(0, 1, 2) << std::endl;
std::cout << get(2, 1, 1) << std::endl;
}