c++ 如何从protobuf repeatedField填充std::数组?

5jvtdoz2  于 2023-03-09  发布在  其他
关注(0)|答案(4)|浏览(348)

从一个定义为正好包含N个元素的RepeatedField开始,我填充了一个std::数组。

std::array<int, 6> entry;
size_t i = 0;
for (const auto& item: msg.items()){
  assert(i < 6);
  entry[i++] = item;
}

这可以正常工作,但是有没有更好的方法来初始化它?填充std::vector可以很好地用于初始化列表,但是std::array是really different
是否可以在包含std::array的结构体的聚合初始化中使用RepeatedFields?
到目前为止,我所尝试的甚至没有编译:

entry = {msg.items().begin(), msg.items().end()};

这是可以理解的,因为std::array没有接受std::initializer_list的构造函数;但我想做的事可能吗?

3bygqnnd

3bygqnnd1#

你可以尝试使用STL算法

std::array<int, 6> entry;
assert(msg.items_size() == std::size(entry));
std::copy(std::begin(msg.items()), std::end(msg.items()), begin(entry));

或者如果你有多个这样的情况,你可以写帮助函数。

template<typename T, size_t N, typename R, size_t...I>
std::array<T, N> range_to_array_impl(R&& r, std::index_sequence<I...>)
{
    return { r[I]... };
}

template<typename T, size_t N, typename R>
std::array<T, N> range_to_array(R&& r)
{
    assert(std::size(r) == N);
    return range_to_array_impl<T, N>(std::forward<R>(r), std::make_index_sequence<N>{});
}

// use:
auto entry = range_to_array<int, 6>(msg.items());

https://godbolt.org/z/zEjorr7Tx

bfnvny8b

bfnvny8b2#

最简单的方法是直接使用聚合初始化

assert(items.size() >= 6)
std::array entry = {
   items[0],items[1],items[2],
   items[3],items[4],items[5],
};

或者你可以写一个函数

template<std::size_t N, typename C>
auto get_array(C&& c){
    assert(c.size() >= N); // or =, depend on the need
    return [&]<std::size_t ...Index>(std::index_sequence<Index...>){
        return std::array{c[Index]...};
    }(std::make_index_sequence<N>{});
}

void foo()
{
    std::array entry = get_array<6>(items);
}
vlurs2pr

vlurs2pr3#

这是一个通用的版本,可以处理intdouble等任意类型。它使用了一个函数模板make_array,循环遍历元素并填充元素。程序使用了vector及其beginend方法。

#include <cstdio>
#include <vector>
#include <array>
#include <iostream>
template<typename T, std::size_t N> std::array<T, N> constexpr make_array(const std::vector<T> &repeatedField)
{
    std::array<T, N> tempArray{};                          //local array that will be returned by value
    auto start = repeatedField.begin();                    //iterator to beginning of vector
    std::size_t pos = 0;                                   //to keep track of position 
    while(pos < N && start!=repeatedField.end())          //loop through the elements of the vector or repeatedfield
    {
        tempArray[pos] = *start;
        ++pos;                                  //update pos 
        start++;                                //update iterator
    }
    return tempArray;
}
int main()
{
    std::vector<int> testingVector{1,2,5,8};
    //--------------------------V-------->number of elements  
    auto arr  = make_array<int, 6>(testingVector);

    
    //lets confirm if all objects have the expected value 
    for(const auto &elem: arr)
    {
        std::cout << elem << std::endl; 
    }
    
}

working demo
将函数模板的签名更改为是**微不足道的

template<typename T, std::size_t N> std::array<T, N> constexpr make_array( std::vector<T>::iterator begin, std::vector<T>::iterator end)

然后在使用/调用它时传递该范围。

ykejflvf

ykejflvf4#

就初始化而言,此模板应执行以下操作:

template<typename e, std::size_t n, typename r>
constexpr array<e,n> init_array(r&& x)->std::array<e,n>{
    assert((n<=size(r)));
    return [&]<std::size_t ...i>(std::index_sequence<i...>){ return {x[i]...};} (make_index_sequence<n>{});
};

auto entry=create_array<int,6>(msg.items());

相关问题