c – 用非默认可构造类型填充std :: array(没有可变参数模板)
作者:互联网
假设我有一个没有默认构造函数的类型A:
struct A
{
int x;
A(int x) : x(x) {}
};
我想创建一个A的std ::数组.我可以使用初始化列表轻松地创建它:
std::array<A, 5> arr = { 0, 1, 4, 9, 16 };
你可以在这里看到一个模式.是的,我可以使用生成器函数来计算数组的每个值:
int makeElement(size_t i)
{
return i * i;
}
std::array<A, 5> arr = {
makeElement(0),
makeElement(1),
makeElement(2),
makeElement(3),
makeElement(4)
};
是的,实际上我有超过5个元素(64,即).所以不重复makeElement 64次会很好.我提出的唯一解决方案是使用可变参数模板将参数包解压缩到初始化列表:https://ideone.com/yEWZVq(它还检查所有副本是否被正确删除).该解决方案的灵感来自this question.
它有效,但我不想滥用可变参数模板来完成这么简单的任务.你知道,膨胀的可执行文件大小,减慢编译速度,所有这些.我想做这样的事情:
>使用适当的大小创建一些未初始化的存储
>使用placement new初始化循环中的所有元素
>将存储转换为std :: array并将其返回
我可以做一些肮脏的黑客在动态内存中实现它:https://ideone.com/tbw5lm但这并不比std :: vector好,我根本没有这样的问题.
我不知道如何在自动记忆中做到这一点.即具有相同的方便函数返回std :: array的值与引擎盖后面的所有这些东西.有任何想法吗?
我想,boost :: container :: static_vector对我来说可能是个很好的解决方案.不幸的是,我无法使用boost来完成该特定任务.
PS.请注意,这个问题更像是研究兴趣.在现实世界中,可变参数模板和std :: vector都可以正常工作.我只是想知道也许我错过了什么.
解决方法:
我认为,你对代码膨胀的担忧被误解了.这是一个示例:
#include <utility>
#include <array>
template<std::size_t... ix>
constexpr auto generate(std::index_sequence<ix...> ) {
return std::array<int, sizeof...(ix)>{(ix * ix)...};
}
std::array<int, 3> check() {
return generate(std::make_index_sequence<3>());
}
std::array<int, 5> glob = generate(std::make_index_sequence<5>());
它产生非常整洁的组件:
check():
movl $0, -24(%rsp)
movl $1, -20(%rsp)
movl $4, %edx
movq -24(%rsp), %rax
ret
glob:
.long 0
.long 1
.long 4
.long 9
.long 16
如你所见,看不到任何代码膨胀.静态数组是静态初始化的,对于自动数组,它只是一堆移动.如果你认为一堆动作是一个可怕的代码膨胀,考虑它循环展开 – 每个人都喜欢!
顺便说一句,没有其他符合要求的解决方案.在构造时使用聚合初始化初始化数组,因此元素应该是默认可构造的或初始化的.
标签:stdarray,c,c14,initialization 来源: https://codeday.me/bug/20191007/1865429.html