用一个元素填充构造std::array
Construct std::array by filling with one element
我有一个列表 class,其中大小变量是 const
成员。这对我很有帮助,因为它强制要求列表的大小可以在 运行 运行 之间变化,但不能在单个 运行.
之间变化
我想创建这些列表的集合。集合中列表的数量是一个模板变量,所以我想使用 std::array
... 即,我想要一个列表数组,其中数组的大小是一个模板参数,并且每个列表的大小是 const
在构建时指定的
不幸的是:
- const-size 列表没有默认构造函数(需要指定其大小!),因此我需要为列表的每个元素提供一个构造函数参数。我不能只创建数组然后设置元素
- 因为我的列表大小是一个模板变量,所以我不能使用标准的初始化列表 - 所需的元素数量各不相同
我知道还有其他选择:
- 我可以使用
std::vector
并且只是 push_back
元素一个接一个,直到向量的大小等于我的模板参数,但这看起来不够优雅,因为它不会自然地强制执行结果向量的大小在完全填充后不应更改的条件。
- 我可以翻转索引排序,并有一个
std::arrays
的常量大小的列表。但是,这与我的其余代码不太吻合;我希望能够将一个单独的常量大小的列表从数组传递给客户端代码
- 我可以为 const 大小的列表创建默认构造函数 class,创建数组,然后使用 placement new 逐个替换数组元素。这似乎会产生一些不良的副作用(const-sized list 的默认构造函数是做什么的?如果它在别处被意外调用怎么办?当我的继任者不知道我做了什么时会发生什么?)
由于其中 none 是完全理想的,我认为如果有一个数组构造函数(或辅助函数)作为参数会很棒:
- T的数组元素个数
- 单个T对象
...and return a std::array<T>
其中每个 T
都是从参数 2.
复制构造的
有这种东西吗?
std::array<T, N>
是一个模板 class,表示 T
类型元素的长度 N
的数组。如果您想创建列表数组,您只需执行 std::array<std::list<T>>, N>
,其中 N
在 编译时 已知。 const std::size_t N
不够,必须是 constexpr
.
所以不,你不能那样做。但是,您可以为此使用 std::vector
。
如果您 post 努力编写一些代码,我们可以想出更好的东西。
好的。模板魔术。由于std::array
是聚合类型,可以使用聚合初始化来初始化:
std::array<T, 5> arr = { one, two, three, four, five };
想法是 one
,...,five
是 T 类型(在您的情况下为列表)构造对象的五个副本,使用用户输入作为参数。那么,让我们玩吧。看完这篇不笑不哭:
想法是取一个类型为 T 的对象,并将其复制五次:
{ T(param), .... }; // Five repetitions.
所以,让我们创建一个 return 数组已经初始化的函数:
std::array<A, 5> arr = create_array_by_copy<5>(A(10));
该函数将 return 一个具有 5
个临时对象副本的 array<A, 5>
。
为此,我们将使用一个辅助 struct
,它将创建一个长度为 5
的参数包(参数化为 s
):
template<std::size_t s, class... voids_t>
struct sized_pack : public sized_pack<s - 1, voids_t..., void>
{};
template<class... voids_t>
struct sized_pack<0, voids_t...>
{};
这将创建一个名为 voids_t
的参数包,它只是 s
void
的列表。现在,技巧的核心:
template<std::size_t s, class T, class... pack_t>
std::array<T, s>
create_array_by_copy_helper(sized_pack<0, pack_t...> const&,
T const& o)
{ return { (pack_t(), o)... }; }
template<std::size_t s, class T>
std::array<T, s> create_array_by_copy(T const& o)
{
return create_array_by_copy_helper<s>(sized_pack<s>(), o);
}
这很复杂。我知道...因为我们已经将 sized_pack<s>
类型的对象传递给辅助函数,该临时对象将实例化 sized_pack
的层次结构,最后一个基数 class 将是类型的对象sized_pack<0, void, void, void, void, void>
.
函数 apply 将接收该对象作为对 size_pack<0, pack_t...>
的引用(最后一个基数 class,注意第一个 0),因此,pack_t
将是我们的 5 列表void
s.
最后,我们有:
(pack_t(), o)
这只是逗号运算符,所以,它 returns o
。这个想法是我们在 "pattern" 中插入了 pack_t
(参数包),因此,当将 ...
应用于表达式时,它将被逗号分隔的表达式替换,其中每个pack_t
appearance 会被参数包中的每个元素按相同的顺序替换,所以:
{ (pack_t(), o)... }
转换为:
{ (void(), o), (void(), o), (void(), o), (void(), o), (void(), o) }
一个初始化列表!!最后,每个元素只是一个 void
表达式,后跟逗号运算符,只有每对中的第二个元素将被逗号运算符 returned。因此,评估的表达式将是:
return { o, o, o, o, o }; // With its corresponding calls to `forward`.
我们想要的初始化列表!!
Coliru 示例:
http://coliru.stacked-crooked.com/a/d6c4ab6c9b203130
您只需将类型 T
替换为您的列表 class。
我有一个列表 class,其中大小变量是 const
成员。这对我很有帮助,因为它强制要求列表的大小可以在 运行 运行 之间变化,但不能在单个 运行.
我想创建这些列表的集合。集合中列表的数量是一个模板变量,所以我想使用 std::array
... 即,我想要一个列表数组,其中数组的大小是一个模板参数,并且每个列表的大小是 const
在构建时指定的
不幸的是:
- const-size 列表没有默认构造函数(需要指定其大小!),因此我需要为列表的每个元素提供一个构造函数参数。我不能只创建数组然后设置元素
- 因为我的列表大小是一个模板变量,所以我不能使用标准的初始化列表 - 所需的元素数量各不相同
我知道还有其他选择:
- 我可以使用
std::vector
并且只是push_back
元素一个接一个,直到向量的大小等于我的模板参数,但这看起来不够优雅,因为它不会自然地强制执行结果向量的大小在完全填充后不应更改的条件。 - 我可以翻转索引排序,并有一个
std::arrays
的常量大小的列表。但是,这与我的其余代码不太吻合;我希望能够将一个单独的常量大小的列表从数组传递给客户端代码 - 我可以为 const 大小的列表创建默认构造函数 class,创建数组,然后使用 placement new 逐个替换数组元素。这似乎会产生一些不良的副作用(const-sized list 的默认构造函数是做什么的?如果它在别处被意外调用怎么办?当我的继任者不知道我做了什么时会发生什么?)
由于其中 none 是完全理想的,我认为如果有一个数组构造函数(或辅助函数)作为参数会很棒:
- T的数组元素个数
- 单个T对象
...and return a std::array<T>
其中每个 T
都是从参数 2.
有这种东西吗?
std::array<T, N>
是一个模板 class,表示 T
类型元素的长度 N
的数组。如果您想创建列表数组,您只需执行 std::array<std::list<T>>, N>
,其中 N
在 编译时 已知。 const std::size_t N
不够,必须是 constexpr
.
所以不,你不能那样做。但是,您可以为此使用 std::vector
。
如果您 post 努力编写一些代码,我们可以想出更好的东西。
好的。模板魔术。由于std::array
是聚合类型,可以使用聚合初始化来初始化:
std::array<T, 5> arr = { one, two, three, four, five };
想法是 one
,...,five
是 T 类型(在您的情况下为列表)构造对象的五个副本,使用用户输入作为参数。那么,让我们玩吧。看完这篇不笑不哭:
想法是取一个类型为 T 的对象,并将其复制五次:
{ T(param), .... }; // Five repetitions.
所以,让我们创建一个 return 数组已经初始化的函数:
std::array<A, 5> arr = create_array_by_copy<5>(A(10));
该函数将 return 一个具有 5
个临时对象副本的 array<A, 5>
。
为此,我们将使用一个辅助 struct
,它将创建一个长度为 5
的参数包(参数化为 s
):
template<std::size_t s, class... voids_t>
struct sized_pack : public sized_pack<s - 1, voids_t..., void>
{};
template<class... voids_t>
struct sized_pack<0, voids_t...>
{};
这将创建一个名为 voids_t
的参数包,它只是 s
void
的列表。现在,技巧的核心:
template<std::size_t s, class T, class... pack_t>
std::array<T, s>
create_array_by_copy_helper(sized_pack<0, pack_t...> const&,
T const& o)
{ return { (pack_t(), o)... }; }
template<std::size_t s, class T>
std::array<T, s> create_array_by_copy(T const& o)
{
return create_array_by_copy_helper<s>(sized_pack<s>(), o);
}
这很复杂。我知道...因为我们已经将 sized_pack<s>
类型的对象传递给辅助函数,该临时对象将实例化 sized_pack
的层次结构,最后一个基数 class 将是类型的对象sized_pack<0, void, void, void, void, void>
.
函数 apply 将接收该对象作为对 size_pack<0, pack_t...>
的引用(最后一个基数 class,注意第一个 0),因此,pack_t
将是我们的 5 列表void
s.
最后,我们有:
(pack_t(), o)
这只是逗号运算符,所以,它 returns o
。这个想法是我们在 "pattern" 中插入了 pack_t
(参数包),因此,当将 ...
应用于表达式时,它将被逗号分隔的表达式替换,其中每个pack_t
appearance 会被参数包中的每个元素按相同的顺序替换,所以:
{ (pack_t(), o)... }
转换为:
{ (void(), o), (void(), o), (void(), o), (void(), o), (void(), o) }
一个初始化列表!!最后,每个元素只是一个 void
表达式,后跟逗号运算符,只有每对中的第二个元素将被逗号运算符 returned。因此,评估的表达式将是:
return { o, o, o, o, o }; // With its corresponding calls to `forward`.
我们想要的初始化列表!!
Coliru 示例:
http://coliru.stacked-crooked.com/a/d6c4ab6c9b203130
您只需将类型 T
替换为您的列表 class。