[英]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标签也可以提供帮助。
#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 ) );
}
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.