一个 class 具有通用等级的数组成员
A class with an array member of generic rank
考虑以下代码示例:
#include <iostream>
#include <tuple>
template<typename T, std::size_t Rank, std::size_t... In>
struct help;
template<typename T, std::size_t... In>
struct help<T, 1, In...>
{
static constexpr auto a = std::make_tuple(In...);
T data[std::get<0>(a)];
};
template<typename T, std::size_t... In>
struct help<T, 2, In...>
{
static constexpr auto a = std::make_tuple(In...);
T data[std::get<0>(a)][std::get<1>(a)];
};
template<typename T, std::size_t... In>
class foo : public help<T, sizeof...(In), In...>
{
private:
using base = help<T, sizeof...(In), In...>;
public:
template<typename... Tn>
constexpr foo(Tn&&... args)
: base{ { args... } } // constructor would only work if rank == 1
{}
T operator[](std::size_t i) noexcept { return base::data[i]; }
constexpr T operator[](std::size_t i) const noexcept { return base::data[i]; }
};
int main()
{
foo<int, 6> a = { 1, 2, 3, 4, 5, 6 };
for (std::size_t i = 0; i < 6; ++i) {
std::cout << a[i] << " ";
}
}
这是我得到的。
我正在尝试制作一个 class,其对象应构造为 foo<int, 2>; foo<int, 3, 4>; foo<int, 1, 2, 3, 4>;
这些对象将分别包含一个 int[2]; int[3][4]; int[1][2][3][4]
.[=16= 类型的数组成员]
我最初的想法是制作一个辅助模板 class,它可以专门化很多(至少直到排名 20 的数组)。这显然很冗长,在我得到一个 2 阶数组后,我不知道 foo
的构造函数应该是什么。
构造函数问题可以通过使 class 成为 POD(无访问说明符等)并通过聚合初始化构造(很像 std::array
做的)来解决,但这与我的工作背道而驰到目前为止 "proper inherited specialization"。
我会很感激一些想法。你会怎么做这样的事情?
我认为你把事情复杂化了。只需创建一个类型特征,为您提供正确的 std::array
类型:
template <class T, size_t... Is>
struct multi_array;
template <class T, size_t... Is>
using multi_array_t = typename multi_array<T, Is...>::type;
维度为零时,您只需得到类型:
template <class T>
struct multi_array<T> {
using type = T;
};
并且至少有一个维度,您只需将其包装在 std::array
中并递归:
template <class T, size_t I, size_t... Is>
struct multi_array<T, I, Is...> {
using type = std::array<multi_array_t<T, Is...>, I>;
};
所以你得到类似的东西:
static_assert(std::is_same<multi_array_t<int, 2>, std::array<int, 2>>::value, "!");
static_assert(std::is_same<multi_array_t<int, 3, 4>, std::array<std::array<int, 4>, 3> >::value, "!");
考虑以下代码示例:
#include <iostream>
#include <tuple>
template<typename T, std::size_t Rank, std::size_t... In>
struct help;
template<typename T, std::size_t... In>
struct help<T, 1, In...>
{
static constexpr auto a = std::make_tuple(In...);
T data[std::get<0>(a)];
};
template<typename T, std::size_t... In>
struct help<T, 2, In...>
{
static constexpr auto a = std::make_tuple(In...);
T data[std::get<0>(a)][std::get<1>(a)];
};
template<typename T, std::size_t... In>
class foo : public help<T, sizeof...(In), In...>
{
private:
using base = help<T, sizeof...(In), In...>;
public:
template<typename... Tn>
constexpr foo(Tn&&... args)
: base{ { args... } } // constructor would only work if rank == 1
{}
T operator[](std::size_t i) noexcept { return base::data[i]; }
constexpr T operator[](std::size_t i) const noexcept { return base::data[i]; }
};
int main()
{
foo<int, 6> a = { 1, 2, 3, 4, 5, 6 };
for (std::size_t i = 0; i < 6; ++i) {
std::cout << a[i] << " ";
}
}
这是我得到的。
我正在尝试制作一个 class,其对象应构造为 foo<int, 2>; foo<int, 3, 4>; foo<int, 1, 2, 3, 4>;
这些对象将分别包含一个 int[2]; int[3][4]; int[1][2][3][4]
.[=16= 类型的数组成员]
我最初的想法是制作一个辅助模板 class,它可以专门化很多(至少直到排名 20 的数组)。这显然很冗长,在我得到一个 2 阶数组后,我不知道 foo
的构造函数应该是什么。
构造函数问题可以通过使 class 成为 POD(无访问说明符等)并通过聚合初始化构造(很像 std::array
做的)来解决,但这与我的工作背道而驰到目前为止 "proper inherited specialization"。
我会很感激一些想法。你会怎么做这样的事情?
我认为你把事情复杂化了。只需创建一个类型特征,为您提供正确的 std::array
类型:
template <class T, size_t... Is>
struct multi_array;
template <class T, size_t... Is>
using multi_array_t = typename multi_array<T, Is...>::type;
维度为零时,您只需得到类型:
template <class T>
struct multi_array<T> {
using type = T;
};
并且至少有一个维度,您只需将其包装在 std::array
中并递归:
template <class T, size_t I, size_t... Is>
struct multi_array<T, I, Is...> {
using type = std::array<multi_array_t<T, Is...>, I>;
};
所以你得到类似的东西:
static_assert(std::is_same<multi_array_t<int, 2>, std::array<int, 2>>::value, "!");
static_assert(std::is_same<multi_array_t<int, 3, 4>, std::array<std::array<int, 4>, 3> >::value, "!");