有没有一种优雅的方法可以从 std::vector 实例化 boost::array?
Is there an elegant way to instantiate a boost::array from a std::vector?
编写接口时,我必须将 std::vector<double>
的实例转换为 boost::array<double,N>
。每次,通过构建(没有错误),我确信向量的大小正确。
这是我目前正在做的一个例子(我有大约 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_);
}
有更短的方法吗?
注 1:出于兼容性原因,我不使用 C++11。
注 2:我添加了标签 stdarray
因为即使它是 C++11 标签也可能有所帮助。
编写模板函数:
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;
}
那么你的函数就会变成一行:
double foo1(const std::vector<double>& x)
{
return foo1_( convert<double,4>( x ) );
}
某事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,", "));
}
但是请记住,这样一个从 运行 时间到编译时间容器的 "translation" 可能是相当危险的,因为它的正确性依赖于 assert
,这是在发布模式中被淘汰。
您可以对元素数量进行模板化(这也是 array<>
正在做的)。如果您明智地对参数进行排序,则可以仅指定大小并仍然推导 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;
}
使用哪个
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));
}
但更好的想法是根据迭代器(或类似 gsl::span
的东西)重新实现 foo1_
和 foo2_
。您可以根据需要assert(std::distance(begin, end) == 4)
编写接口时,我必须将 std::vector<double>
的实例转换为 boost::array<double,N>
。每次,通过构建(没有错误),我确信向量的大小正确。
这是我目前正在做的一个例子(我有大约 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_);
}
有更短的方法吗?
注 1:出于兼容性原因,我不使用 C++11。
注 2:我添加了标签 stdarray
因为即使它是 C++11 标签也可能有所帮助。
编写模板函数:
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;
}
那么你的函数就会变成一行:
double foo1(const std::vector<double>& x)
{
return foo1_( convert<double,4>( x ) );
}
某事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,", "));
}
但是请记住,这样一个从 运行 时间到编译时间容器的 "translation" 可能是相当危险的,因为它的正确性依赖于 assert
,这是在发布模式中被淘汰。
您可以对元素数量进行模板化(这也是 array<>
正在做的)。如果您明智地对参数进行排序,则可以仅指定大小并仍然推导 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;
}
使用哪个
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));
}
但更好的想法是根据迭代器(或类似 gsl::span
的东西)重新实现 foo1_
和 foo2_
。您可以根据需要assert(std::distance(begin, end) == 4)