创建 C 数组包装器(更好的 std::array?)
Creating a C array wrapper (a better std::array?)
这是一个简单的二维 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 }
} };
问题在于,大括号省略算法始终将 c 数组成员视为单个实体。如果内部初始化器以大括号开头,则该算法需要一个包含一个元素的初始化器列表。因此,解决方案是以大括号省略算法知道包装器聚合了多少元素的方式定义 carray 包装器。
为此,我看到的唯一解决方案是通过多重继承来模拟一个数组:
#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}};
这是一个简单的二维 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 }
} };
问题在于,大括号省略算法始终将 c 数组成员视为单个实体。如果内部初始化器以大括号开头,则该算法需要一个包含一个元素的初始化器列表。因此,解决方案是以大括号省略算法知道包装器聚合了多少元素的方式定义 carray 包装器。
为此,我看到的唯一解决方案是通过多重继承来模拟一个数组:
#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}};