Visual Studio 2010和早期版本附带的std::vector
的实现具有众所周知的特殊性:resize
方法具有以下签名(符合C ++ 03):
void resize(size_type new_size, value_type value);
而不是C ++ 11之前很久以来大多数其他STL实现(如gcc的STL或STLport)使用的符合C ++ 11的签名:
void resize(size_type new_size, const value_type& value);
第一个变体的问题在于,在某些情况下,如果value_type
具有对齐规范,则无法编译:
struct __declspec(align(64)) S { ... };
std::vector<S> v; // error C2719: '_Val': formal parameter with __declspec(align('64')) won't be aligned
这是一个well known问题,除了使用std::vector
的不同实现外,没有令人满意的解决方法。
我正在寻找一个写得很好,经过良好测试,自包含和STL兼容的std::vector
实施,并且有麻省理工学院风格的许可证,我可以放入我的project作为对齐类型的首选容器。
我考虑过从STLport或gcc的STL中提取它,但是,由于完全符合标准,它们都很大,并且具有许多非平凡的依赖性。
(对于只支持std::vector
,push_back
,clear
,capacity
的{{1}}合理子集的实现,我会非常满意, size
,reserve
,resize
和数组索引。)
有什么想法吗?
答案 0 :(得分:8)
Eigen库后面的人似乎找到了一个很好的解决方法来解决存储&#34;过度排列的类型&#34; (as Stephan T. Lavavej call them)到Visual Studio的STL中实现的std::vector
。
它们的实现似乎不必要复杂(检查源here和here),但主要思想是使用瘦包装器封装进入std::vector
的类型:
#include <vector>
template <typename T>
struct wrapper : public T
{
wrapper() {}
wrapper(const T& rhs) : T(rhs) {}
};
struct __declspec(align(64)) S
{
float x, y, z, w;
};
int main()
{
std::vector< wrapper<S> > v; // OK, no C2719 error
return 0;
}
关于Eigen的实施,我必须承认我不太了解
Eigen::aligned_allocator_indirection
,EIGEN_WORKAROUND_MSVC_STL_SUPPORT
,Eigen::workaround_msvc_stl_support
,resize
分配器std::vector
部分专业化重新定义Eigen::aligned_allocator_indirection
... 线索欢迎。关键是,这个技巧完美无缺(据我所知)并且我没有看到任何错误,除了可能有点不合时宜。
答案 1 :(得分:1)
最简单(也是最好的,imho)选项是提供一个自由函数作为vector
接口的扩展,它做了正确的事情。您需要实现resize
的所有功能都可以从std::vector
的公共界面获得:
#include <vector>
template<class T, class Alloc>
void resize(std::vector<T, Alloc>& v,
typename std::vector<T, Alloc>::size_type new_size, T const& val)
{
if (v.size() < new_size)
v.insert(v.end(), new_size - v.size(), val);
else if (new_size < v.size())
v.erase(v.begin() + new_size, v.end());
}
为了保持一致,单个参数版本:
template<class T, class Alloc>
void resize(std::vector<T, Alloc>& v,
typename std::vector<T, Alloc>::size_type new_size)
{
v.resize(new_size); // simply forward
}
但是,如果你只想放入新的向量而不用担心自由或成员函数,另一种选择就是简单地继承std::vector
:
#include <vector>
#include <memory>
template<class T, class Alloc = std::allocator<T>>
class myvector
: public std::vector<T, Alloc>
{
typedef std::vector<T, Alloc> base;
public:
typedef typename base::size_type size_type;
void resize(size_type new_size){
base::resize(new_size);
}
void resize(size_type new_size, T const& val){
if (this->size() < new_size)
this->insert(this->end(), new_size - this->size(), val);
else if (new_size < this->size())
this->erase(this->begin() + new_size, this->end());
}
};
请注意,我还提供了resize
的单个参数版本,因为两个参数版本将隐藏所有基类版本。另请注意,我需要使用this->
为所有成员函数调用添加前缀,因为它们依赖于基类std::vector
,并且在模板参数上也是如此。