[英]How do I initialise a std::array field inside a struct with the contents of a variable length sequence container?
I have a struct which in an extremely simplified representation looks like this:我有一个结构体,它以极其简化的表示形式如下所示:
struct Flags {
const std::array<unsigned int, 8> flags;
Flags(std::vector<unsigned int> initialFlagValues) : flags(initialFlagValues) {}
};
Which of course does not compile.这当然不能编译。 For the purposes of my program, I'd like to initialise an arbitrary number of elements in
flags
, depending on the length of a parameter ( std::vector
, C-style array, or otherwise) passed into the constructor of the struct.就我的程序而言,我想初始化
flags
任意数量的元素,具体取决于传递到结构构造函数的参数( std::vector
、C 样式数组或其他)的长度。
Now I'd like to use a std::array
inside the struct, as the struct itself is created many times (so a std::vector
would not be ideal here due to many allocations/deallocations), but the number of values within flags
that need to be initialised is not always the same.现在我想在结构中使用
std::array
,因为结构本身被创建了很多次(因此由于许多分配/释放, std::vector
在这里不是理想的),但是里面的值的数量需要初始化的flags
并不总是相同的。
Is there a way I can initialise a specific number of fields in flags
depending on the size of the sequence container passed as a parameter into the constructor?有没有一种方法可以根据作为参数传递给构造函数的序列容器的大小来初始化
flags
特定数量的字段?
Use a helper function, perhaps in the form of a lambda:使用辅助函数,可能是 lambda 的形式:
Flags(std::vector<unsigned int> initialFlagValues) :
flags([](const auto& init) {
std::array<unsigned int, 8> flags;
// bounds check omitted for brevity
std::copy(init.begin(), init.end(), flags.begin());
return flags;
}(initialFlagValues))
{}
Maybe the helper function can be a delegated constructor也许辅助函数可以是委托构造函数
struct Flags
{
std::array<unsigned int, 8u> const flagsArr;
template <std::size_t ... Is>
Flags (std::vector<unsigned int> iFV, std::index_sequence<Is...>)
: flagsArr{ Is < iFV.size() ? iFV[Is] : 0u ... }
{}
Flags (std::vector<unsigned int> iFV)
: Flags{iFV, std::make_index_sequence<8u>{}}
{}
};
You can generalize with for generic types supporting operator []
and std::size()
(so also C-style arrays) as follows您可以对支持运算符
[]
和std::size()
(C 样式数组)的泛型类型进行概括,如下所示
struct Flags
{
std::array<unsigned int, 8u> const flagsArr;
template <typename T, std::size_t ... Is>
Flags (T const & iFV, std::index_sequence<Is...>)
: flagsArr{ Is < std::size(iFV) ? iFV[Is] : 0u ... }
{}
template <typename T>
Flags (T const & iFV)
: Flags{iFV, std::make_index_sequence<8u>{}}
{}
};
std::array
is an aggregate. std::array
是一个聚合。 That means the only way to initialized it is with a braced_init_list ( {}
).这意味着初始化它的唯一方法是使用braced_init_list (
{}
)。 There is no way to convert a std::vector
into a braced_init_list so one thing you can do is to use a loop inside the constructor like没有办法将
std::vector
转换为braced_init_list所以你可以做的一件事就是在构造函数中使用一个循环,比如
Flags(std::vector<unsigned int> initialFlagValues) : flags{} // zero out flags
{
auto size = std::min(initialFlagValues.size(), flags.size())
for (size_t i = 0; i < size; ++i)
flags[i] = initialFlagValues[i];
}
This will nessecitate that flags
be non-const.这将使
flags
成为非常量。 If that is a change you can't make, then you'll need to make initialFlagValues
a std::array
, or use a helper function to return an array that you can use to initialize flags
with.如果这是您无法进行的更改,则您需要将
initialFlagValues
std::array
,或使用辅助函数返回可用于初始化flags
的数组。
You can also do everything at (almost) compile-time, with no iterations:您还可以在(几乎)编译时完成所有操作,无需迭代:
#include <iostream>
#include <type_traits>
#include <iterator>
struct Omg {
static constexpr std::size_t SIZE = 8;
template<class Container> Omg(Container &&c)
: Omg(std::forward<Container>(c), std::make_index_sequence<SIZE>{})
{}
void omg() const {
for(auto i: array) std::cout << i << ' ';
std::cout << '\n';
}
private:
template<class C, std::size_t... is> Omg(C &&c, std::index_sequence<is...>)
: array{get<is>(std::forward<C>(c))...}
{}
template<std::size_t i, class C> static constexpr auto get(C &&c) {
return i < std::size(c)? c[i] : 0;
}
std::array<int, SIZE> array;
};
int main() {
Omg(std::vector<int>{0, 1, 2, 3}).omg();
int nyan[] = {42, 28, 14};
Omg(nyan).omg();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.