为什么在改变std::vector的分配器时初始化列表不可用?
Why are initializer lists not available when changing the allocator of std::vector?
在我的项目中,我将使用的点类型从Eigen::Vector2f
更改为Eigen::Vector2d
,并遇到对齐问题。
下面是代码的简化版本:
#include <vector>
#include <Eigen/Eigen>
int main()
{
std::vector<Eigen::Vector2d> points = { {0,0}, {0,1} };
}
我得到以下运行时错误:
eigen3/Eigen/src/Core/DenseStorage.h:78: Eigen::internal::plain_array<double, 2, 0, 16>::plain_array() [T = double, Size = 2, MatrixOrArrayOptions = 0, Alignment = 16]: Assertion `(reinterpret_cast<size_t>(array) & 0xf) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****"' failed.
正如断言消息所建议的那样,我了解了固定大小的可向量化特征对象所需的对齐方式。还有关于STL容器的小节。我似乎有两个选择:
- 使用
Eigen::aligned_allocator
- 或使用
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION
宏。
两个尝试都不能编译(在GCC 4.8.3和Clang 3.5中测试),因为编译器不能正确转换初始化项列表。
修改后的代码:
#include <vector>
#include <Eigen/Eigen>
#include <Eigen/StdVector>
// EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d)
int main()
{
std::vector<Eigen::Vector2d, Eigen::aligned_allocator<Eigen::Vector2d>> points = { {0,0}, {0,1} };
// std::vector<Eigen::Vector2d> points = { {0,0}, {0,1} };
}
GCC错误输出
error: could not convert ‘{{0, 0}, {0, 1}}’ from ‘<brace-enclosed initializer list>’ to ‘std::vector<Eigen::Matrix<double, 2, 1>, Eigen::aligned_allocator<Eigen::Matrix<double, 2, 1> > >’
所以我想知道:
为什么在更改
std::vector
的分配器时初始化列表不可用?- 这是因为对齐吗?
- 我能以某种方式对齐初始化列表吗?
为什么专门化版本失败?
- 这些是否缺少初始化列表功能?
在研究了Eigen/StdVector
包含文件(确切地说,它是在版本3.2.1的Eigen/src/StlSupport/StdVector.h
第68行)之后,似乎问题源于此头文件中std::vector
的部分模板专门化。一旦使用Eigen::aligned_allocator
作为分配器,这个部分模板专门化就会替换STL vector
。而且这种专门化似乎缺少c++ 11的特性。
除了替换分配器之外,详细说明为什么需要这个专门化:在c++ 11之前,std::vector
的resize函数可以接受一个附加形参来初始化新创建的元素。根据Eigen3文档,按值传递参数将丢弃任何对齐修饰符,并且不能用于固定大小的可向量化特征对象(参见SIMD)。
经过更多的测试,我意识到std::vector
的c++ 11实现没有上述问题。因此,要解决对齐问题,您只需填写Eigen::aligned_allocator
。但是不包含Eigen/StdVector
。包含此文件将阻止您使用std::vector
的c++ 11实现,因为此头文件定义了Eigen::aligned_allocator
作为分配器的部分专门化。
- C++类 - 初始化列表 - 递归 - 按值传递
- 在初始化列表之外手动调用基类的构造函数
- C++:带有大括号初始化列表的函数调用表达式 - 标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
- std::map与谓词与初始化列表
- 类内初始化与构造函数初始化列表的顺序
- 当返回语句时,逗号运算符、大括号初始化列表和 std::unique_ptr 组合在一起
- 使用初始化列表填充C++中的多维结构数组时出现问题
- 如何在初始化列表中的构造函数之后初始化变量/对象?
- C++初始化列表与分配值
- C++初始化列表中的向量集大小或调整大小
- 在构造函数初始化列表中使用 std::variant
- emplace_back初始化列表错误,当初始化列表在独立变量上工作时
- 解释了构造函数成员初始化列表
- 使用初始化列表时如何获取私有数据?
- 用初始化列表和超类构造函数声明子类构造函数的正确方式
- 如何在成员初始化列表中声明共享指针
- 庞大的初始化列表,如何修复"fatal error C1060: compiler is out of heap space"
- 我可以检查初始化列表中设置的构造函数主体中的变量吗
- 使用整数初始化列表初始化长双精度的向量
- 是否可以在C++中使用初始化列表设置数组的特定成员?