繁体   English   中英

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

[英]How do I initialise a std::array field inside a struct with the contents of a variable length sequence container?

我有一个结构体,它以极其简化的表示形式如下所示:

struct Flags {
    const std::array<unsigned int, 8> flags;

    Flags(std::vector<unsigned int> initialFlagValues) : flags(initialFlagValues) {}
};

这当然不能编译。 就我的程序而言,我想初始化flags任意数量的元素,具体取决于传递到结构构造函数的参数( std::vector 、C 样式数组或其他)的长度。

现在我想在结构中使用std::array ,因为结构本身被创建了很多次(因此由于许多分配/释放, std::vector在这里不是理想的),但是里面的值的数量需要初始化的flags并不总是相同的。

有没有一种方法可以根据作为参数传递给构造函数的序列容器的大小来初始化flags特定数量的字段?

使用辅助函数,可能是 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))
{}

也许辅助函数可以是委托构造函数

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>{}}
    {}
};

您可以对支持运算符[]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是一个聚合。 这意味着初始化它的唯一方法是使用braced_init_list ( {} )。 没有办法将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];
}

这将使flags成为非常量。 如果这是您无法进行的更改,则您需要将initialFlagValues std::array ,或使用辅助函数返回可用于初始化flags的数组。

您还可以在(几乎)编译时完成所有操作,无需迭代:

#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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM