C++ 张量的编译时索引/元组访问

use*_*370 2 c++ compile-time variadic-templates c++17 c++20

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

Art*_*yer 5

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

// 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...);
}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 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';
}
Run Code Online (Sandbox Code Playgroud)