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
}
我有一个编译时张量 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
}