更改std :: vector的分配器时,为什么初始化程序列表不可用?

mic*_*mic 15 c++ memory-alignment initializer-list c++11 eigen3

在我的项目中,我将使用过的点类型更改Eigen::Vector2fEigen::Vector2d并遇到了对齐问题.

这是代码的简化版本:

#include <vector>
#include <Eigen/Eigen>

int main()
{
    std::vector<Eigen::Vector2d> points = { {0,0}, {0,1} };
}
Run Code Online (Sandbox Code Playgroud)

我收到以下运行时错误:

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.
Run Code Online (Sandbox Code Playgroud)

正如断言消息所示,我读到了固定大小的可矢量化特征对象所需的对齐.还有关于STL容器的小节.似乎我有两个选择:

  1. 使用 Eigen::aligned_allocator
  2. 或使用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} };
}
Run Code Online (Sandbox Code Playgroud)

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> > >’
Run Code Online (Sandbox Code Playgroud)

所以我想知道:

  • 为什么在更改分配器时初始化程序列表不可用std::vector

    • 这是因为对齐吗?
    • 我可以以某种方式对齐初始化列表吗?
  • 为什么专业化版本失败了?

    • 这些缺少初始化列表功能吗?

mic*_*mic 15

在研究了Eigen/StdVector包含文件之后(准确地说它是在Eigen/src/StlSupport/StdVector.h版本3.2.1的第68行),似乎问题源于std::vector此头文件中的部分模板特化.vector只要您Eigen::aligned_allocator用作分配器,此部分模板专用就会替换STL .而这种专业化似乎缺乏C++ 11的功能.

详细为什么这种专业化是必要除了更换分配器: 前C++ 11的调整大小功能std::vector可以由值取一个额外的参数来初始化新创建的元素.根据Eigen3文档,按值传递参数会丢弃任何对齐修饰符,并且不能与固定大小的可矢量化特征对象一起使用(请参阅SIMD).

编辑: 经过一些测试后,我意识到C++ 11的实现std::vector并没有上述问题.因此,要解决对齐问题,您需要填写Eigen::aligned_allocator.但包括在内Eigen/StdVector.包含此文件将阻止您使用C++ 11实现,std::vector因为此标头定义了具有Eigen::aligned_allocatoras allocator 的部分特化.