【问题标题】:Creating a C array wrapper (a better std::array?)创建一个 C 数组包装器(更好的 std::array?)
【发布时间】:2018-12-02 16:16:29
【问题描述】:

这是一个简单的二维 C 样式数组示例:

int c[2][2] = {
    { 1, 2 },
    { 3, 4 }
};

如果我希望这是std::array,我必须使用它:

std::array<std::array<int, 2>, 2> c = {
    { { 1, 2 } },
    { { 3, 4 } }
};

声明比较复杂,我必须使用额外的{}进行初始化。

是否可以创建一个 C 风格的数组包装器,我可以用它来做到这一点?

my_array<int, 2, 2> c = {
    { 1, 2 },
    { 3, 4 }
};

所以声明更简单,不需要额外的{}

如果可以创建这样的东西,与std::array相比,这个解决方案是否有一些缺点?


我已经做到了:

template <typename T, std::size_t ...S>
struct ArrayTypeHelper;

template <typename T, std::size_t HEAD, std::size_t ...TAIL>
struct ArrayTypeHelper<T, HEAD, TAIL...> {
    using Type = typename ArrayTypeHelper<T, TAIL...>::Type[HEAD];
};
template <typename T, std::size_t HEAD>
struct ArrayTypeHelper<T, HEAD> {
    using Type = T[HEAD];
};

template <typename T, std::size_t ...S>
struct my_array {
    typename ArrayTypeHelper<T, S...>::Type data;
};

但这仍然需要额外的{}

my_array<int, 2, 2> b = { {
    { 1, 2 },
    { 3, 4 }
} };

【问题讨论】:

  • std::array&lt;std::array&lt;int, 2&gt;, 2&gt; c{1, 2, 3, 4}; 怎么样?
  • 使用 C++17 可以更简单,因为它可以从初始化中推断出模板参数。
  • @VTT:我不太喜欢这种风格。并且有些编译器会对此发出警告。
  • @geza 我猜“一些编译器”是指clang?然后是known bug。您仍然可以将每一行保留在单独的行上,使其看起来像矩阵

标签: c++ c++17 c++20


【解决方案1】:

问题是大括号省略算法总是将 c 数组成员视为单个实体。如果内部初始化程序以大括号开头,则算法需要一个包含一个元素的初始化程序列表。因此解决方案是定义数组包装器,使大括号省略算法知道包装器聚合了多少元素。

为此,我看到的唯一解决方案是通过多重继承来模拟数组:

#include <utility>
using namespace std;

template<class T,size_t DeDuplicate>
struct holder{
  T val;
  };

template<class T,class IndSeq>
struct carray_wrapper_b;

template<class T,size_t...Is>
struct carray_wrapper_b<T,index_sequence<Is...>>
  :holder<T,Is>...
  {   };

template<class T,size_t I,size_t...Is>
struct make_carray_{
  using type = carray_wrapper_b<typename make_carray_<T,Is...>::type
                               ,make_index_sequence<I>>;
  };
template<class T,size_t I>
struct make_carray_<T,I>{
  using type = carray_wrapper_b<T,make_index_sequence<I>>;
  };

template<class T,size_t...Is>
using carray_wrapper = typename make_carray_<T,Is...>::type;

carray_wrapper<int,2,2>  x = { {1,2},{3,4}};
carray_wrapper<int,2,2>  y = { 1,2,3,4};

这个数组包装器也可以仅用于初始化目的:

template<class T,size_t I,size_t...Is>

struct carray{
  carray(initializer_list<T>);
  carray(initializer_list<carray_wrapper<T,Is...>>);
  };

carray<int,2,2,3> arr{1,2,3,4,5,6,7};
carray<int,2,2,3> arr2{{1,2},{3,4}};
carray<int,2,2,3> arr3{{{1,2},{3,4}},{1,2}};

【讨论】:

  • 不错的技巧,谢谢奥利夫!如果可以的话,我会更多地支持这个答案,它应该得到超过 2 个。
  • @geza 谢谢 :)
猜你喜欢
  • 2017-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多