简体   繁体   English

如何使用可变长度序列容器的内容初始化结构内的 std::array 字段?

[英]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.

相关问题 如何在 std::array (容器)中初始化指向 Object 的指针? - How do I initialise a Pointer to a Object inside a std::array (container)? 如何使用函数的输出初始化 const 数组结构字段? - How do I initialise a const array struct field with the output of a function? std::variant 中具有可变长度数组的结构 - struct with variable length array in std::variant 如何使用 std::tuple 等原始数组成员初始化元组<t[n]> ?</t[n]> - How do I initialise a tuple with a raw array member such as std::tuple<T[N]>? 如何将std :: string内容克隆到新的char []数组中 - How do I clone std::string contents to a new char[] array 如何使用 std::generate 初始化具有值的 constexpr 数组 - How can I initialise a constexpr array with values using std::generate 如何在不提供构造函数的情况下创建和初始化简单的结构? - How do I create and initialise a simple struct without providing a constructor? 在C ++ 11中初始化一个C ++ std :: array的struct - initialise a C++ std::array of struct in C++11 使用 std::index_sequence 初始化具有固定大小数组成员的 POD 结构容器 - using std::index_sequence to initialize POD struct container with fixed size array members 如何初始化另一个结构中的结构数组? - How to initialise array of structs in another struct?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM