【问题标题】:A class with an array member of generic rank具有通用等级数组成员的类
【发布时间】:2016-03-31 18:36:56
【问题描述】:

考虑以下代码示例:

#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] << " ";
    }
}  

这是据我所知。

我正在尝试创建一个类,其对象应构造为foo&lt;int, 2&gt;; foo&lt;int, 3, 4&gt;; foo&lt;int, 1, 2, 3, 4&gt;; 这些对象将分别保存int[2]; int[3][4]; int[1][2][3][4] 类型的数组成员。

我最初的想法是制作一个非常专业的辅助模板类(至少在 20 级数组之前)。这显然是冗长的,在我得到一个排名为 2 的数组之后,我不知道 foo 的构造函数应该是什么。

可以通过使类成为 POD(无访问说明符等)并通过聚合初始化(很像 std::array 所做的那样)构造来解决构造函数问题,但这与我迄今为止的“正确继承的专业化”的工作背道而驰”。

我会很感激一些想法。你会怎么做这样的事情?

【问题讨论】:

  • 为什么需要数组成员?你能通过多个operator[] 模拟相同的行为吗?

标签: c++ templates c++11 generic-programming


【解决方案1】:

我认为你把事情复杂化了。只需创建一个类型特征,即可为您提供正确的 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, "!");

【讨论】:

  • 我确实过于复杂了。可能是因为我没有考虑 std::array 而是考虑 C 数组。真正优雅的解决方案。谢谢!
  • @DeiDei 你也可以对原始数组做同样的事情,只是改变递归步骤。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
  • 2017-11-14
  • 1970-01-01
  • 2015-11-01
  • 2015-05-25
相关资源
最近更新 更多