简体   繁体   English

有没有一种优雅的方法来从std :: vector实例化boost :: array?

[英]Is there an elegant way to instantiate a boost::array from a std::vector?

Writing an interface, I have to convert instances of std::vector<double> to boost::array<double,N> . 编写接口时,我必须将std::vector<double>实例转换为boost::array<double,N> Each time, by construction (without bug), I'm sure the vector has the right size. 每次,通过构造(没有bug),我确定矢量具有正确的大小。

Here is an example of what I'm currently doing (I have about 100 such functions to write in the interface) : 这是我正在做的事情的一个例子(我在接口中有大约100个这样的函数):

double foo1(const std::vector<double>& x)
{
  assert(x.size() == 4);
  boost::array<double,4> x_;
  for(std::size_t i = 0; i < 4; ++i)
    x_[i] = x[i];
  return foo1_(x_);
}

double foo2(const std::vector<double>& x)
{
  assert(x.size() == 6);
  boost::array<double,6> x_;
  for(std::size_t i = 0; i < 6; ++i)
    x_[i] = x[i];
  return foo2_(x_);
}

Is there a shorter way to do that ? 有没有更短的方法呢?

Note 1: I don't use C++11 for compatibility reasons. 注1:出于兼容性原因,我不使用C ++ 11。

Note 2: I added tag stdarray because it can maybe help even if it's a C++11 tag. 注2:我添加了标签stdarray因为即使它是C ++ 11标签也可以提供帮助。

Something like this : 像这样的东西:

#include <boost/array.hpp>
#include <vector>
#include <boost/range/algorithm.hpp>
#include <iostream>
#include <cassert>

template<size_t Size, class Container>
boost::array<typename Container::value_type, Size> as_array(const Container &cont)
{
    assert(cont.size() == Size);
    boost::array<typename Container::value_type, Size> result;
    boost::range::copy(cont, result.begin());
    return result;
}

int main()
{
    // this is C++11 initialization, but the rest of code is C++03-complient
    std::vector<int> v{1, 2, 3};
    boost::array<int, 3> a = as_array<3>(v);
    boost::range::copy(a, std::ostream_iterator<int>(std::cout,", "));
}

But keep in mind that such a "translation" from a run-time to a compile-time container might be quite dangerous, as its correctness relies on assert , which is eliminated in release mode. 但请记住,从运行时到编译时容器的这种“转换”可能非常危险,因为它的正确性依赖于assert ,这在发布模式中被消除。

Write a template function: 写一个模板函数:

template<class T,size_t N>
std::array<T,N> convert( const std::vector<T> & v )
{
    //assert(v.size() == N);
    std::array<T,N> r;
    std::copy( v.begin(), v.end(), r.begin() );
    return r;
}

then your functions will become one liners: 那么你的功能将成为一个衬里:

double foo1(const std::vector<double>& x)
{
    return foo1_( convert<double,4>( x ) );
}

live example 实例

You can template over the number of elements (That's what array<> is doing too). 你可以模拟元素的数量(这就是array<>正在做的事情)。 If you order the parameters sensibly, you can specify just the size and have double still deduced 如果你明智地订购参数,你可以只指定尺寸并且仍然可以推导出double

template<std::size_t N, typename T>
boost::array<T, N> from_vector(const std::vector<T> & vec)
{
    assert(x.size() == N);
    boost::array<T, N> res;
    std::copy(vec.begin(), vec.end(), res.begin());
    return res;
}

Which gets used 哪个被使用了

double foo1(const std::vector<double> & vec)
{
    return foo1_(from_vector<4>(vec));
}

double foo2(const std::vector<double> & vec)
{
    return foo2_(from_vector<6>(vec));
}

But a better idea would be to re-implement foo1_ and foo2_ in terms of iterators (or something like gsl::span ). 但更好的想法是在迭代器(或类似gsl::span )方面重新实现foo1_foo2_ You can assert(std::distance(begin, end) == 4) as needed 您可以根据需要assert(std::distance(begin, end) == 4)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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