簡體   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