C++ 编译时 index/tuple 访问张量

C++ Compile time index/tuple access for tensor

我有一个编译时张量 class。现在我想像这样实现索引访问:

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;
}

但遗憾的是,这无法编译。有谁知道我如何实现这个? 当我的张量为 const 时,它也需要工作。我也可以使用元组而不是可变参数模板。如果需要,我可以使用最现代的 compiler/cpp 标准。

您不能折叠 [](用于多维索引)。您可以使用一对函数实现此目的:

// 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...);
}

如果您使用的是 C++2b,则可以使用带有多个参数的 operator[],这可能更易于使用:

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';
}

您可以使用 C++20 <ranges> 来展平多维 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;
  std::cout << get(0, 1, 2) << " "; // 3
  get(0, 1, 2) = 42;
  std::cout << myTensor[0][1][2] << " "; // 42
}

Demo